XCircuit Embedded Python Interpreter Reference


The command line functions are written in Python, if Python has been compiled into xcircuit. Whether this is true is indicated by the command-line prompt when the '%' macro is chosen, which is a question mark ('?') if the interpreter is the old-style xcircuit interpreter, and the usual Python prompt ('>>>') if the interpreter is Python.

The Python command line syntax accepts any valid Python code. Special functions in the embedded interpreter, imported as a module, link the Python interpreter to internal xcircuit variables. These special commands are summarized below.

Python Script Examples

The file included with the distribution, "examples/test.py", shows how to do animation using the Python commands, as well as showing the basics of creating new commands and using basic capabilities of the interpreter to handle variables and simple math functions.

Other files included in the "psfiles/python/" directory are intended for use with xcircuit, as extensions to xcircuit commands. At any given time, some of these functions may be under develpment. Functions which are operational and of interest are listed below.

Python Commands in the XCircuit Module

Python Commands for XCircuit Object Manipulation

(See section below for Python command implementing aspects of the Xw GUI.)

Override system startup defaults. Necessarily, these commands are only useful when included in the .xcircuitrc file, and have no effect when run from the command line or executed from a script. option can be one of:
Sets the designated xcircuit global (default) option. The keyword "default" is redundant. option can be one of:
library("filename" [, number])
Add filename (a .lps file) to the User Library (default), or to the library page designated by number. If the designated library page does not exist, it will be created.
Add fontname to the list of known fonts. Preferably there should be corresponding font encoding and vector files for accurate character drawing, but this is not a necessity.
Add color colorname to the list of known colors. The color name can be in #RGB (hexidecimal, 0x00-0xff) or R, G, B (decimal, 0-255) format.
Resets the current page, deleting all elements.
Changes the current page to the page indicated by number.
bind(["key_name" [, "function_name"]])
Bind the indicated key to the indicated function.
unbind("key_name", "function_name")
Unbinds the indicated key from the indicated function.
dict = getobject(name)
Returns a dictionary with the contents of the named object. Contents are the object name (key="name"), width (key="width") and height (key="height"), a list of parameter strings (key="parameters"), and a list of parts by handle (see below).
dict = getlibrary(name)
Returns a dictionary dict containing the name of the library (key="name") and a list of objects (key="objects"). The list of objects is a list of object names. Individual object contents can be retrieved with the "getobject" command.
dict = getpage(number)
Returns dictionary dict containing page parameters and a list of handles to all elements on the page. Without any options, getpage() returns information about the current page.
dict = getattr(handle)
Returns a dictionary dict containing key:value pairs for all the properties of the element addressed by handle. handle may be obtained through getpage() or newelement(). See below for definitions of individual elements.
setattr(handle, dict)
Applies the key:value pairs from dict to the element addressed by handle. The property (key) "type" cannot be changed. See below for definitions of individual elements.
handle = newelement("typename")
Creates a new element of the indicated type on the current page, and returns a handle to it. The handle may be used to get and set all properties of the element. Valid types are:

Python Commands Implementing Simple Interaction

These commands are not available in the standard XCircuit. Use of pause() and refresh() allow the creation of simple animations.
Pause for the indicated amount of time value, in seconds. The pause() function can be used to implement animated graphics. Pending graphics events are handled during pauses, so pause() does not lock up the program until the indicated period has passed.
Redraw the xcircuit screen. This should be used in conjunction with the pause() command for animation. On the command line, refresh() is executed after every command. In a script, no screen refresh occurs until called explicitly.
scale = zoom(factor)
Zoom by the indicated (floating-point) amount factor, where values greater than 1 indicate a zoom-in, and values less than 1 indicate a zoom-out. The returned value is the scale of the page after zooming.
corner = pan(location)
Pan the screen such that the new screen center is placed at user coordinates indicated by the (X,Y) tuple location. location may also be two integers representing the X and Y positions. The value corner returned is an (X,Y) tuple holding the position of the screen's lower left-hand corner in user coordinates.

Python Commands Implementing Simple GUI Extensions

Python may use the tkinter functions to implement GUI functions. However, to keep the ``look and feel'' of the Xw widgets interface presently used by XCircuit, several Python functions are provided to generate the same kind of popup and menu button widgets. These commands are listed below.
tuple = getcursor()
Returns a tuple containing the X and Y coordinates (in xcircuit units) of the cursor.
Generates a popup window which prompts for a value. The window is titled with the text passed in prompt. The result of selecting return or pressing the "okay" button will be to call the Python function callback. This callback function should expect one parameter, which will be the string entered into the popup text edit window by the user.
Operates the same way as popupprompt(), but includes a directory search window.
Operates the same way as popupprompt(), but produces a window with the prompt (informational) string prompt and buttons for the choices "Okay" and "Cancel". If "Okay" is selected, then the Python function named callback will be called. callback should be a function which expects no parameters.
newbutton(menu, label, callback)
Creates a new entry in the xcircuit menu named menu. The new entry will be added at the bottom, and the name on the menu button will be the text of label. Pressing the button calls a function callback, which should be a function expecting no parameters.

Python Commands for Schematic Capture

dict = netlist()
Generate a dictionary dict representing the circuit netlist as captured from the current page.
This will eventually replace virtually all of XCircuit's handling of netlist information. When the netlist() function is called from Python, XCircuit generates the netlist as usual, but rather than attempt to format the output itself, it passes the netlist information back to Python as a dictionary, letting Python scripts sort out the information and determine how to write the output format. This gives a greater flexibility in the implementation, allowing the end-user to modify the output format for, say, a particular implementation of SPICE, or to automatically insert headers and trailers, or generate output compatible with other CAD tools.

See below for a detailed explanation of the contents of the netlist dictionary returned to Python.

List of Key Bindings for XCircuit

bind(["key_name" [, "function_name"]])
Bind the indicated key to the indicated function.

Special cases:
str = bind("value") (one argument)
Returns a string representation of all the bindings associated with the indicated key or function value.

dict = bind() (no argument)
Returns a dictionary of all key:function bindings.

Key names follow the convention of /usr/X11/include/ksymdefs.h, except: Function names are case-sensitive. Valid function names are:
function name function description default binding
"Page" number Go to indicated page 1 through 9, 0
"Justify" number Text justification KP_1 through KP_9
"Superscript" Start text superscripting KP_Add
"Subscript" Start text subscripting KP_Subtract
"Normalscript" End text sub- or superscript KP_Enter
"Nextfont" Switch to next font in list Alt_f
"Boldfont" Change to boldface font Alt_b
"Italicfont" Change to italic font Alt_i
"Normalfont" Change to normal font Alt_n
"Underline" Start text underline Alt_u
"Overline" Start text overline Alt_o
"ISO Encoding" Change to ISO-Latin1 encoding Alt_e
"Halfspace" Insert half-space Alt_h
"Quarterspace" Insert quarter-space Alt_q
"Special" Insert special character \
"Tab Stop" Define tab stop Alt_Tab
"Tab Forward" Tab forward Tab
"Tab Backward" Tab backward Shift_Tab
"Text Return" Finish text edit Enter
"Text Delete" Delete last character Delete
"Text Right" Move right one character Right
"Text Left" Move left one character Left
"Text Home" Move to label beginning Home
"Text End" Move to label end End
"Return Char" Insert carriage-return Alt_Enter
"Parameter" Insert parameter value Alt_p
"Edit Break" Break polygon at point x
"Edit Delete" Delete polygon point d
"Edit Insert" Insert polygon point i
"Edit Next" Go to next edit point e
"Attach" Attach edit point to element A
"Next Library" Go to next library l
"Library Directory" Go to library directory L
"Library Move" Move objects within library M
"Library Copy" Return to page in copy mode c
"Library Edit" Edit an object name E
"Library Delete" Delete a library object D
"Library Duplicate" Duplicate a library object C
"Library Hide" Hide a library object H
"Page Directory" Go to page directory P
"Library Pop" Return from library >
"Help" Generate help window h, ?
"Redraw" Redraw the drawing window Space
"View" Center the current drawing v
"Zoom In" Enlarge the view Z
"Zoom Out" Shrink the view z
"Pan" Move window center to cursor position p
"Double Snap" Double the snap spacing +
"Halve Snap" Halve the snap spacing -
"Pan Left" Pan left one-half screen width Left
"Pan Right" Pan right one-half screen width Right
"Pan Up" Pan up one-half screen height Up
"Pan Down" Pan down one-half screen height Down
"Write" Pop up output properties window W
"Rotate" number Rotate element r, R, o, O
"Flip X" Flip element horizontal f
"Flip Y" Flip element vertical F
"Snap" Snap element to snap grid S
"Pop" Return from current edit <
"Push" Edit object >
"Delete" Delete element Delete
"Select" Select element Button2
"Box" Generate box b
"Arc" Generate arc a
"Text" Generate label t
"Exchange" Exchange order of elements X
"Copy" Make copy of an element c
"Join" Join elements into a path j
"Unjoin" Separate path into elements J
"Spline" Generate a Bezier curve s
"Edit" Edit an element e
"Undelete" Retrieve last deleted element u
"Select Save" Create new library object M, m
"Unselect" Unselect an element x
"Dashed" Change border to dashed style |
"Dotted" Change border to dotted style :
"Solid" Change border to solid style _
"Prompt" Prompt for Python command %
"Dot" Create a "solder dot" .
"Wire" Start a wire (polygon) w, Button1
"Start" Start command (general) Button1
"Finish" End command (general) Button2, Shift_Button1
"Cancel" Cancel command (general) Button3
"Nothing" Null command (general) Button3
"Exit" Quit XCircuit Control_Alt_q
"Netlist" Generate Python netlist Alt_q
"Swap" Move schematic <--> symbol /
"Pin Label" Generate "Pin" label T
"Info Label" Generate "Info" label I
"Connectivity" See network connectivity Alt_w
"Sim" Generate "sim" format output Alt_s
"SPICE" Generate "SPICE" format output Alt_Shift_S
"PCB" Generate "PCB" format output Alt_p
"SPICE Flat" Generate flattened SPICE output Alt_f
Those functions indicated with "number" take a parameter as part of the function name; e.g., "Page 1" and "Page 2" are two different bindings, as is "Rotate 3" (rotate clockwise 15 degrees) and "Rotate -3" (rotate counterclockwise 15 degrees).

Python Structures Generated by XCircuit

In addition to the functions which can be called from the interpreter command-line, it is necessary to be able to understand the structures which are returned. Some of these (especially the circuit netlist) are quite complicated, and require a thorough description.

XCircuit Element Output to Python

The getattr() command assembles a dictionary describing an element. The dictionary key is always a Python string object. The value associated with the key and the actual keys used depends on the element. Key/value pairs are listed for each element below:
dict = { "type" : "Polygon",
"color" : colorval,
"style" : styleval,
"linewidth" : widthval,
"points" : pointlist }
dict = { "type" : "Arc",
"color" : colorval,
"style" : styleval,
"linewidth" : widthval,
"radius" : intval,
"minor axis" : intval,
"start angle" : floatval,
"end angle" : floatval,
"position" : pointval }
Bezier Curves
dict = { "type" : "Bezier Curve",
"color" : colorval,
"style" : styleval,
"linewidth" : widthval,
"control points" : pointlist }
Object Instances
dict = { "type" : "Object Instance",
"color" : colorval,
"name" : stringval,
"position" : pointval,
"rotation" : intval,
"scale" : floatval }
dict = { "type" : "Path",
"color" : colorval,
"style" : styleval,
"linewidth" : widthval,
"parts" : partslist }
dict = { "type" : "Label",
"color" : colorval,
"position" : pointval,
"rotation" : intval,
"scale" : floatval,
"justify" : justval,
"pin" : pinval,
"string" : xcstringval }
Sub-parts of the above dictionary are defined below:
Any integer

Any floating-point value

Any normal (Python) string

Either a 3-Tuple of color component values (R, G, B), where each value ranges from 0 to 255, or the string "Default" for automatic color inheritance. To set a color value, a string containing the color name may also be used. The integer color index is also accepted, but is not recommended due to system dependance.

Integer value representing the style. Because this is a bitmask relevant only to xcircuit, it will probably be replaced by another dictionary of key:value pairs representing each style bit and its True/False status. For now, see the PostScript output page for an explanation of the bitmask.

Integer value representing justification. The value is a modified bitmask, and will probably be replaced by a dictionary with more meaningful terms. For now, see the PostScript output page for an explanation of the value.

Integer value representing the type of label, indicating if the label is a pin. This value will probably be replaced with a string representing the type, but for now the value is 0 for a normal text label, 1 for a local pin, 2 for a global pin, and 3 for an info label.

Floating-point value representing a linewidth. This number is relative to the ``natural'' xcircuit wire width (1.0).

rgbval = ( R, G, B )
Color as a 3-tuple of integer R, G, and B components.

partslist = [ element1, element2, ... elementN ]
List of elements

An xcircuit element, indexed by handle (address pointer to structure location, converted to an integer)

pointlist = [ pointval1, pointval2, ... pointvalN ]
List of points.

pointval = ( X, Y )
Each point is a tuple of X, Y values where X and Y are integers.

xcstringval = [ stringpart1, stringpart2, ... stringpartN ]
Each string is a list of parts.

stringpart = stringdictpart | stringstringpart
Each string part can be either a dictionary (string part requires a value) or a string (string part does not take a value).

Can be one of the following dictionaries with a single key:value pair:
{ "Text" : stringval }
{ "Parameter" : intval }
{ "Font" : stringval }
{ "Font Scale" : floatval }
{ "Kern" : pointval }
{ "Color" : rgbval }

Can be one of the following strings:
"End Parameter"
"Tab Stop"
"Tab Forward"
"Tab Backward"
"No Line"
"Half Space"
"Quarter Space"

Page and Object Output to Python

The getobject() and getpage() commands return a slew of information which can be useful for manipulating objects, generating new interactive commands, and building animation sequences. The dictionaries returned are described in detail below.
pagedict = { "filename" : stringval,
"page label" : stringval,
"output scale" : floatval,
"grid space" : intval,
"snap space" : intval,
"orientation" : intval,
"output mode" : intval,
"coordinate style" : intval,
"page size" : pointval,
"drawing scale" : pointval }

Dictionary definition for pages.

"page size"
While "page size" is type pointval ((X,Y) tuple), the interpretation is X=page width, Y=page height.

"drawing scale"
While "drawing scale" is type pointval ((X,Y) tuple), the interpretation is a ratio of drawn measurements to actual measurements of X:Y.

"gridspace", "snapspace"
"gridspace" and "snapspace" are in xcircuit units, not natural units. This is likely to change in the future. The default gridspace is 32 and the default snapspace is 16, in these units.

"orientation" is an angle value. Currently only "0" (portrait) and "90" (landscape) are valid.

"output mode"
"output mode" will probably be changed to a more meaningful string value in the future. For now, a value of "0" means full-page output, value "1" means encapsulated (EPS) output. A value of "2" means full-page, auto-scaled output.

"coordinate style"
"coordinate style" will probably be changed to a more meaningful string value in the future. For now, a value of "0" means decimal inches, "1" means fractional inches, and "2" means centimeters.

objectdict = { "name" : stringval,
"width" : intval,
"height" : intval,
"viewscale" : floatval,
"viewcorner" : pointval,
"boundingbox" : pointval,
"parts" : partslist,
"parameters" : paramlist }

Dictionary definition for objects (see above for definition of partslist and paramlist).

The "boundingbox" defines the lower left-hand corner of the object's bounding box, in xcircuit units. The whole bounding box can be derived by adding the "width" and "height" values.

Page View
The "viewcorner" and "viewscale" values determine how the circuit is displayed within the xcircuit drawing window. These values are not saved to the output file, so when a file is read, each page is centered on the window. The "viewcorner" is in xcircuit coordinates.
Note that pages and page objects are separate things; every page has an associated object (the "page object"), but not every object has an associated page (e.g., library objects). The "page label" entry for a page is the name of the associated page object.

User (xcircuit) units to window (X11) units conversion. Note that due to the graph-like layout of xcircuit, the Y user axis follows the standard mathematical convention of increasing Y values toward the top of the window, whereas X11 follows the opposite convention of increasing Y values toward the bottom of the window.


  For any pointval value P, P[0] = X value, P[1] = Y value.
  U = pointval, user coordinate, tuple (X,Y).
  W = pointval, window coordinate, tuple (X,Y).
  viewscale = floatval, scale conversion between user and window coordinates.
  viewcorner = pointval, in user coordinates, tuple (X,Y)
  window_height = pixel height (X11 coordinates) of the XCircuit window.
User (xcircuit) to window (X11) units conversion:
  W[0] = (U[0] - viewcorner[0]) * viewscale
  W[1] = window_height - (U[1] - viewcorner[1]) * viewscale
Window (X11) to user (xcircuit) units conversion:
  U[0] = W[0] / viewscale + viewcorner[0]
  U[1] = (window_height - W[1]) / viewscale + viewcorner[1]

Netlist Output to Python

The netlist() command returns a dictionary to Python which must be interpreted to figure out how any output format should be written. This netlist dictionary contains all netlist information which should be relevant to any netlist output format. XCircuit is responsible for the actual schematic capture, meaning that XCircuit determines what is and isn't a wire, determines the circuit hierarchy, finds which subcircuits are called with which networks as parameters, and cleans up the netlist with respect to trivial objects such as jumpers, pin-terminating circles, ``solder-dots,'' etc. Flattening netlists requires following a protocol unique to a given format, so flattening is the responsibility of Python, too.

Important note: I changed the format between xcircuit-2.5.4 revision 7 and revision 8. The change is to denote nets by number instead of name, and provide a dictionary for each subcircuit equating net numbers to names. The separation of nets from their names makes it much easier to flatten netlists by remapping the net numbers when visiting each subcircuit call.

rdict = { "globals" : globals,
"circuit" : circuit }
Dictionary returned has two components, a list of globals, and the circuit itself.

globals = { intval1 : xcstringval1, intval2 : xcstringval2, ... intvalN : xcstringvalN }
A dictionary of global networks. "xcstringval1", etc., are the names of the networks, returned as an xcircuit label, which is a list of label parts (see above). "intval1", etc., are the numbers associated with each global net name. These numbers are negative to differentiate them from local net numbers.

circuit = [ subckt1, subckt2, ... subcktN ]
A list of subcircuits, of which the last one is the top-level circuit.

subckt = { "ports" : portlist
"parameters" : paramlist
"calls" : calllist
"nets" : netlist
"devices" : devicelist }
Subcircuit definition.

portlist = [ intval1, intval2, ... intvalN ]
A list of ports which are the subcircuit input/output nets. Each port number corresponds to a net which is either defined in the globals dictionary of the top-level circuit or the netlist dictionary of the subcircuit. Corresponding net names can be retrieved by dictionary lookup.

paramlist = [ paramvalue1, paramvalue2, ... paramvalueN ]
A list of parameters. paramvalue can be either an xcstringval, if the parameter is a string, or intval if the parameter is a simple integer (as yet unimplemented. Presently, numerical parameters do not affect the netlist, so they are not part of the netlist output).

netlist = { intval1 : xcstringval1, intval2 : xcstringval2, ... intvalN : xcstringvalN }
A dictionary of net number to net name bindings. intval is the net number (integer), and xcstringval is the corresponding name (local to the subcircuit).

calllist = { callval1, callval2, ... callvalN }
A list of calls to subcircuits of this circuit.

callval = { "name" : xcstringval,
"parameters" : paramlist,
"ports" : portlist }
A dictionary returned for each call. This dictionary declares the name of the subcircuit being called, declares any parameters defined in the subcircuit by this instance of the subcircuit object, and declares a portlist. The portlist is similar to the subcircuit's portlist, except that it defines the network number of the network which connects to the indicated port. If no network connects to a particular port, its entry is NULL.

devicelist = [ xcstringval1, xcstringval2, ... xcstringvalN ]
A list of devices defined by this subcircuit. Generally speaking, a subcircuit represents either one or zero devices; however, each device can be represented in different ways according to the output type (SPICE, sim, pcb, etc.). One xcstringval is returned for each info label found in the object (schematic AND symbol checked).

For more information about Python, see python.org.

Back to the xcircuit home page. . .

email: tim@bach.ece.jhu.edu