Skip to content

PainterQubits/PySon

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

9 Commits
 
 
 
 
 
 
 
 

Repository files navigation

PySon

Description

Package for interfacing with Sonnet to automate designing geometries, running simulations, and post-processing data.

Inspired by and initially made as a wrapper to the SonnetLab MatLab library. However, SonnetLab is no longer a required dependency.

Table of Contents

Getting Started

Requirements

Installation

First, install Python dependencies with pip,

pip install numpy matplotlib scikit-rf shapely

Then simply place pyson.py in an accessible folder and import it via,

import pyson
  • Matlab engine / Sonnetlab support

    Begin by downloading Sonnetlab from here, rename the code’s parent directory to “sonnetlab,” and place it in the same directory as pyson.py for example like this:

    Sonnetlab Setup

    Next if you are using a version of Sonnet unsupported by Sonnetlab (16.52 included!) you will need to edit SonnetPath.m to the following

    aSonnetPath='C:\\Program Files (x86)\\Sonnet Software\\16.52';
    aSonnetInstallDirectoryList={'C:\\Progra~2\\Sonnet Software\\16.52'};
    aSonnetInstallVersionList='"00-00-0000"';
    return

    Next to get Matlab engine to work run the following commands

    • As administrator in CMD.exe:
    cd “matlabroot\\extern\\engines\\python”
    python setup.py install
    
    • In MATLAB
    cd (fullfile(matlabroot, ‘extern’, ‘engines’,’python))
    system (‘python setup.py install’)
    
    

User Documentation

pyson.open_son

open_son(file_name, sonnet_path="", temp=False, ml_backend=False, overwrite=None)

Opens an existing Sonnet file with a given name. Returns a PySon project.

  • Arguments

    file_name: str

    Name / directory of Sonnet file

    sonnet_path: str, optional

    Directory for specific sonnet version. Default is C:\Program Files (x86)\Sonnet Software\16.52\bin\” **
    temp: Bool, optional

    Dangerous. Deletes Sonnet file and all generated directories upon garbage collection. Not recommended for open_son and primarily for internal use.

    ml_backend: bool, optional

    Use Matlab / Sonnetlab backend rather than native parser. Enables some extra features and may have better compatibility and stability with some Sonnet versions.

    overwrite: PySon project, optional

    Requires ml_backend. Overwrites an existing matlab engine instance rather than spawning a new one. Reduces resource overhead and speeds up project creation.

  • Examples

    pyson.open_son("project_files\\existing.son")

pyson.new_son

new_son(file_name, sonnet_path="", temp=False, ml_backend=False, overwrite=None)

Creates a new Sonnet file with a given name. Returns a PySon project.

  • Arguments

    file_name: str

    Name / directory of Sonnet file

    sonnet_path: str, optional

    Directory for specific sonnet version. Default is C:\Program Files (x86)\Sonnet Software\16.52\bin\”

    temp: Bool, optional

    Deletes Sonnet file and all generated directories upon garbage collection.

    ml_backend: bool, optional

    Use Matlab / Sonnetlab backend rather than native parser. Enables some extra features (but restricts others) and may have better compatibility and stability with some Sonnet versions.

    overwrite: PySon project, optional

    Requires ml_backend. Overwrites an existing matlab engine instance rather than spawning a new one. Reduces resource overhead and speeds up project creation.

  • Examples

    pyson.new_son("project_files\\new.son")

pyson.from_template

from_template(file_name, new_file="", sonnet_path="", temp=False, ml_backend=False, overwrite=None)

Use an existing Sonnet file as a template to create a new file. Returns a PySon project.

  • Arguments

    file_name: str

    Name / directory of Sonnet template file

    new_file: str, optional

    Name / directory of output file. Default is {file_name}-{1,2,…}.son

    sonnet_path: str, optional

    Directory for specific sonnet version. Default is C:\Program Files (x86)\Sonnet Software\16.52\bin\”

    temp: Bool, optional

    Deletes Sonnet file and all generated directories upon garbage collection.

    ml_backend: bool, optional

    Use Matlab / Sonnetlab backend rather than native parser. Enables some extra features (but restricts others) and may have better compatibility and stability with some Sonnet versions.

    overwrite: PySon project, optional

    Requires ml_backend. Overwrites an existing matlab engine instance rather than spawning a new one. Reduces resource overhead and speeds up project creation.

  • Examples

    pyson.from_template("project_files\\template.son", new_file="output_file.son")

project.save

save(file_name="")

Save a PySon project to disk. Returns nothing.

  • Arguments

    file_name: str, optional

    Name / directory of Sonnet project if not the same as before.

  • Examples

    project = pyson.new_son("new.son")
    # Apply modifications
    project.save()

project.add_metal_polygon

add_metal_polygon(metalization_level, xcoords, ycoords, metal_type="", tech_layer="", inherit=True, header=[])

Add a metal polygon to the project. Returns a polygon id.

  • Arguments

    metalization_level: int

    Level to add polygon

    xcoords: array-like floats

    List of x coordinates for vertices.

    ycoords: array-like floats

    List of y coordinates for vertices. **

    metal_type: str, optional

    Name of metal to use, default is lossless superconductor.

    tech_layer: str, optional

    Name of tech layer if metal is added as part of it.

    header: array-like, optional

    Array of overriding properties for the polygon. Primarily for internal use.

  • Examples

    xc = [50,150,150,50]
    yc = [50,50,150,150]
    project.add_metal_polygon(0,xc,yc)

project.add_std_port

add_std_port(polygon, vertex, port_number=None, res=50, react=0, ind=0, cap=0)

Adds a port to the selected polygon and vertex. Returns a port number.

  • Arguments

    polygon: int

    ID on which to add a port

    vertex: int

    Vertex after which to add a port i.e. vertex=2 places a port on the edge between the 2nd and 3rd vertices.

    port_number: int, optional

    Force a certain port_number instead of incrementing by 1. **

    res: float, optional

    Port resistance.

    react: float, optional

    Port reactance.

    ind: float, optional

    Port inductance.

    cap: float, optional

    Port capacitance.

  • Examples

    xc = [50,150,150,50]
    yc = [50,50,150,150]
    box = project.add_metal_polygon(0,xc,yc)
    project.add_std_port(box, 0)

project.delete_polygon

delete_polygon(index)

Deletes a polygon, supported only in Python backend. Returns nothing.

  • Arguments

    index: int

    Polygon ID to delete.

  • Examples

    box = project.add_metal_polygon(0,xc,yc)
    project.delete_polygon(box)

Known Bugs:

project.box_size

box_size()

Returns two floats (x size, y size)

  • Examples

    x,y = project.box_size()

project.change_box_size

change_box_size(x,y)

Changes box size to specified values. Returns nothing.

  • Arguments

    x: float

    New x size for box

    y: float

    New y size for box

  • Examples

    project.change_box_size(200,200)

project.cell_size

cell_size()

Returns two floats (x size, y size)

  • Examples

    cx,cy = project.cell_size()

project.change_cell_size

change_cell_size(x,y)

Changes cell size to specified values. Returns nothing.

  • Arguments

    x: float

    New cell x size

    y: float

    New cell y size

  • Examples

    project.change_cell_size(0.1,0.1)

project.change_dielectric_layer_thickness

change_dielectric_layer_thickness(layer, thickness)

Changes thickness of a specified dielectric layer. Returns nothing.

  • Arguments

    layer: int

    Layer index to change.

    thickness: float

    New thickness for layer

  • Examples

    # Set the 0-th layer to be 200 units thick
    project.change_dielectric_layer_thickness(0,200)

project.set_valvar

set_valvar(name, value=None, vartype=None, descr=None)

Set a Sonnet project variable. Returns nothing.

  • Arguments

    name: string

    Variable to change.

    value: float, optional

    New value for layer. None ⇒ unchanged.

    *vartype: str **

    Variable type as a string. None ⇒ unchanged.

    Length: “LNG”

    Inductance: “IND”

    Other type strings can be found by opening the .son file as a txt and searching for valvar.

    descr: str, optional

    Variable description. None ⇒ unchanged.

  • Examples

    Consider the following inductor controlled by a variable:

    Valvar Setup

    We can set its values to this:

    Valvar Changed

    Using this:

    project.set_valvar("L1", 21.22, "IND", "Ideal Component Value")

project.add_abs_frequency_sweep

add_abs_frequency_sweep(start,stop)

Set an adaptive frequency sweep range. Returns nothing.

  • Arguments

    start: float

    Sweep start frequency

    stop: float

    Sweep stop frequency

  • Examples

    # Add a sweep from 6 to 8 GHz (standard units)
    project.add_abs_frequency_sweep(6,8)

project.set_speed

set_speed(speed)

Set simulation coarseness / edge meshing level, dictates speed and memory usage. Returns nothing.

  • Arguments

    speed: int

    Coarseness / edge meshing level (0,1,2 where 0 is finest/slowest).

  • Examples

    # Set coarseness / edge meshing to fine
    project.set_speed(0)

project.targ_abs

targ_abs(resolution)

Set the target number of frequencies to measure from an adaptive frequency sweep. Disabled if res_abs is enabled. Returns nothing.

  • Arguments

    resolution: int

    Number of frequencies to target.

  • Examples

    project.targ_abs(300)

project.res_abs

res_abs(enable, resolution)

Set the desired resolution for an adaptive frequency sweep. Disables res abs. Returns nothing.

  • Arguments

    enable: bool

    Enable a specific resolution rather than a target number of frequencies.

    resolution: float

    Resolution to target.

  • Examples

    # Set coarseness / edge meshing to fine
    project.set_speed(0)

project.add_mdif_output

add_mdif_output(file_output="")

Add an mdif output to simulations. Returns nothing.

  • Arguments

    file_output: str, optional

    MDIF file to output to. Default is $BASENAME.mdf, which is the sonnet file but with .son →.mdf.

  • Examples

    add_mdif_otuput("out.mdf")

project.rm_mdif_output

rm_mdif_output(file_output="")

Remove a set mdif output, however, it does not delete any files. Returns nothing.

  • Arguments

    file_output: str, optional

    MDIF output to remove. Default to remove is $BASENAME.mdf.

  • Examples

    rm_mdif_output("out.mdf")

project.simulate_network

simulate_network(file_output="")

Runs a Sonnet EM simulation of the current project. Returns a Scikit-RF NetworkSet where (if a sweep hasn’t otherwise been defined) the 0-th element is the simulation network.

  • Arguments

    file_output: str, optional

    MDIF file to output to. Default creates a temporary file that is removed afterwards.

  • Examples

    # Run a simulation from 6-8GHz and get its skrf.Network
    project.add_abs_frequency_sweep(6,8)
    network = project.simulate_network()[0]

project.sonnet_call_em

sonnet_call_em(file_name="", options="")

Run sonnet EM on a file with the given options. Generally for internal use. Returns nothing.

  • Arguments

    file_name: str, optional

    File to run EM.exe on

    options: str, optional

    Options to run EM.exe with

  • Examples

    project.sonnet_call_em(project.file_name)

project.draw

draw(layer=None, metal_args=dict(color="#209fb5", edgecolor="#4c4f69", hatch="///"), 
             metal_argf = None, ports=True, figsize=(5,5), 
             port_box=dict(boxstyle="square", fc="#eff1f5", ec="#4c4f69", alpha=1), port_font_size=8)

Draws a sonnet project using matplotlib. Returns matplotlib figure and axes objects.

  • Arguments

    figsize: (int, int), optional

    Size of plot

    layer: int, optional

    Layer to draw. Default is the top layer that contains metal.

    metal_args: dict, optional

    Arguments to pass to each fill function when drawing metal.

    metal_argf: function, optional

    Function to run to determine each fill function’s arguments, function is passed the polygon format described in pyson.extract_polygons. Overwrites metal_args.

    ports: bool, optional

    Enable drawing ports

    port_box: dict, optional

    Box parameters for port. Passed to plt.text(bbox=port_box)

    fontsize: float, optional

    Port font size

  • Examples

    Both of these examples use the simple box / port designed in project.add_metal_polygon and project.add_std_port.

    # Basic draw
    fig, ax = project.draw()
    # Fancy gray / labeled drawing using metal_argf
    metal_argf = lambda x: dict(color="lightgrey", label=("Tech Layer " + str(x[-2]) if x[-2] is not "" else "Metal " + str(x[0])))
    fig, ax = project.draw(figsize=(20,20), port_font_size=20, metal_argf=metal_argf)
    xlim(0,200)
    ylim(0,200)
    
    #remove duplicate labels
    handles, labels = gca().get_legend_handles_labels()
    newLabels, newHandles = [], []
    for handle, label in zip(handles, labels):
        if label not in newLabels:
            newLabels.append(label)
            newHandles.append(handle)
    
    legend(newHandles, newLabels, loc=2, prop={'size':28})
    xlabel("Width (µm)", fontsize=28)
    xticks(fontsize=26)
    yticks(fontsize=26)
    ylabel("Height (µm)", fontsize=28)

Parser Documentation

project.son_dict

project.son_dict

Not a function. Dictionary parses the Sonnet file and uses blocks as keys and strings for each line in the individual block. Additionally the file header is stored under “file_header” and the block “GEO” is not parsed into individual lines due to its particularly complicated nature.

  • Examples

    The following lines in the .son file:

    CONTROL
    ABS
    OPTIONS  -d
    SPEED 0
    CACHE_ABS 1
    Q_ACC N
    END CONTROL
    

    Would be parsed as follows:

    project.son_dict["CONTROL"] = ['ABS', 'OPTIONS -d', 'SPEED 0', 'CACHE_ABS 1', 'Q_ACC N']
    

pyson.extract_polygons

extract_polygons(unpacked)

Extract polygons from an unpacked dict of a sonnet file. Complicated return type.

  • Arguments

    unpacked: dict

    Dictionary corresponding to a Sonnet project.

  • Returns

    Returns a list of lists of the form,

    [header, [vertex0, vertex1,...]]
    header = [metalization level, number of vertices, metal_type, ?, ID, ?, ?, ?, ?, ? ,? , ? , ? , ?, tech_layer, inherits]
    vertex0 = [x0,y0]

    Corresponding to each polygon in the project. Question marks indicate a parameter that is not understood and is fixed to some common default.

  • Examples

    # Get the first polygon listed in the file and find its ID
    polys = extract_polygons(project.son_dict)
    poly_id = polys[0][0][4]

pyson.extract_ports

extract_ports(unpacked, indices=False)

Extract ports from an unpacked dict of a sonnet file. Complicated return type.

  • Arguments

    unpacked: dict

    Dictionary corresponding to a Sonnet project.

    indices: bool, optional

    Whether to return a list of line numbers corresponding to ports instead of the list of port dicts.

  • Returns

    Either returns line numbers corresponding to ports (indices=True) or a list of dicts with the following elements depending on port type.

    # STD / All
    port_type
    poly
    points
    vertex
    port_number
    resistance
    reactance
    inductance
    capacitance
    x
    y
    
    # CUP
    calib_group
    cup_group
    cup_group_type
    cup_id
    cup_grndref
    cup_twtype
    
    # AGND
    agnd_calib_type
    agnd_plane_Length
    agnd_calib_length
  • Examples

    # Get the first port listed in the file and get its attached polygon
    ports = extract_ports(project.son_dict)
    poly = ports["poly"]

pyson.extract_ports

extract_box(unpacked)

Extract box data from an unpacked dict of a sonnet file. Complicated return type.

  • Arguments

    unpacked: dict

    Dictionary corresponding to a Sonnet project.

  • Returns

    Returns a list with two lists, the first is the details of the box and the second is a list of lists corresponding to each defined layer.

    [box, [layer0, layer1,...]]
    box = [?, x_size, y_size, x_cell_number, y_cell_number, ?, ?]
    layer0 = [thickness, ?, ?, ...]
  • Examples

    # Get the x dimension of the box
    box = pyson.extract_box(project.son_dict)
    x = box[0][1]

pyson.repack_geo

repack_geo(unpacked, polygons=None, ports=None, box=None)

Repack the geometry section of an unpacked Sonnet dict. Returns a Sonnet dict.

  • Arguments

    unpacked: dict

    Dictionary corresponding to a Sonnet project.

    polygons: list

    List of polygons as discussed in extract_polygons.

    ports: list

    Not implemented

    box: list

    Box parameters / list of layers as discussed in extract_box.

  • Examples

    # Unpack polygons, and directly repack them doing nothing
    new_dict = pyson.repack_geo(project.son_dict, polygons=pyson.unpack_polygons(project.son_dict))

pyson.param_exists

param_exists(unpacked, block, param)

Check if a certain parameter exists in a block of the Sonnet dict (see Sonnet dict documentation). Returns a boolean.

  • Arguments

    unpacked: dict

    Dictionary corresponding to a Sonnet project

    block: string

    Block of the Sonnet dict to check

    parameter: string

    Parameter to find

  • Examples

    # Check if a resolution block exists for frequency sweeps
    check = param_exists(project.son_dict, "CONTROL", "RES_ABS")

pyson.replace_param

param_exists(unpacked, block, param, value)

Set a parameter in the Sonnet dict (see Sonnet dict documentation). Returns nothing.

  • Arguments

    unpacked: dict

    Dictionary corresponding to a Sonnet project

    block: string

    Block of the Sonnet dict to check

    parameter: string

    Parameter to find

    value: string, int, Bool or Array-like

    Value to set parameter

  • Examples

    # Set the resolution for frequency sweeps
    replace_param(project.son_dict, "CONTROL", "RES_ABS", 1.0e-4)

TODO

Known Bugs

  • Support for vias and dielectric bricks is not implemented, and there will likely be significant issues opening files containing them.
  • Different default dimensions between Python backend and Matlab backend (length in terms of um for Python instead of mil). For Python this is intentional, however, consistent behavior is desirable.

Short-term Features

  • Important: need to handle dimensions better, allow changing dimensions, and make it more clear what dimensions are being used.
  • Via support, dielectric brick support
  • Support more frequency sweep options (not just ABS)
  • Better handling of adding/removing ports
  • Finish crop function (unfinished attempt can be seen in code)
  • Linux support (should be as easy as changing directory paths and removing .exe extensions)

Long-term features

  • Better understand polygon / box formats and move towards a dict structure instead of the messy arrays
  • Better understand GEO block as a whole and parameterize it.
  • Overall move towards a less hacky system of modifying the larger sonnet dict structure.
  • Support several Sonnet versions

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages