XCircuit Embedded Python Interpreter Reference

Introduction

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.

gettext.py
Generates a new function "gettext(filename)" in python
which will load an ASCII file into an xcircuit text
label and drop it on the screen at the position of the
cursor. In addition, it defines a command "prompttext()"
to generate a popup window for selecting the desired
text file, uses the "bind" command to bind this function
to the "G" key, and uses the "newbutton" command to add a
button to the xcircuit "Edit" menu which performs the same
function as the key.

pagebbox.py
Adds new functions including "newbox(lx, ly, ux, uy)",
"pagebbox(w, h)", and others (see the source), creates
a menu button under the "Edit" menu which generates a
standard 8.5 x 11 inch bounding box with the lower
left-hand corner on the page origin, and also attaches
this function to the 'Ctrl-B' key combination. The
'B' key prompts for a "width x height"
(in inches) string to define an arbitrary-sized bounding
box.

spice.py
This function is not yet completed. However, it shows the
general method intended for netlist output via the Python
interface. Python calls the "netlist" function, which
returns a complicated Python object representing the
netlist. Python is then responsible for producing the
output format. It is intended that this function and
related functions will
replace the existing netlist output methods, as it is
more general, and capable of being extended or modified
by the end-user without requiring changes to the xcircuit
source.

Similar functions: flatspice.py (flattened SPICE).

loadlgf.py
This function is not yet completed. However, it shows the
general method intended for loading different file formats
via the Python interface. Python is responsible for opening
the file, determining the file type, reading the file, and
generating xcircuit pages, libraries, and objects based on
the contents. It is intended that eventually this function
and related functions will replace the existing file input
methods, as it is more general, and capable of being extended
or modified by the end-user without requiring changes to the
xcircuit source.

panzoom.py (in the examples/ directory)
This function demonstrates how internal xcircuit functions
can be replaced with custom code. Here, the xcircuit "zoom
in" and "zoom out" functions are rewritten to first include
a center pan to the cursor position. The Python script
defines the new functions, unbinds the original zoom functions
from the "Z" and "z" keys, and binds the new functions to the
same keys.

Python Commands in the XCircuit Module

Python Commands for XCircuit Object Manipulation

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:

"library"
Don't load libraries from the startup script.
Libraries are expected to be listed individually using
the "library" command. No libraries are loaded otherwise.
Library elements will be loaded as usual into the "User
Library" page from input files.

"color"
Don't use the pre-defined set of colors.
Colors are expected to be listed individually using the
"color" command. Necessarily for basic operation, black
and white will always be defined. Colors will also be
loaded as required from input files.

"font"
Don't load fonts from the startup script. Instead,
a list of fonts is expected to follow with the
"font" command. Necessarily for basic operation,
one font will be loaded so that object names can be
listed. Other fonts will be loaded as required from
input files.

"key"
Don't use the default key bindings. Macros will
be completely disabled until defined by the "bind"
command through a script or the command-line.

set(option)

Sets the designated xcircuit global (default) option. The keyword
"default" is redundant. option can be one of:

"font", "fontname"
Set the default font of fontname, which will be loaded
if it does not already exist in the list of fonts. The font
name incorporates font style (italic, bold) and encoding
(Adobe standard, ISO).

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.

font("fontname")

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.

color("colorname")

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.

reset()

Resets the current page, deleting all elements.

page(number)

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:

Arc

Bezier Curve

Polygon

Label

Object Instance

Path

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(value)

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.

refresh()

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.

popupprompt(prompt,callback)

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.

filepopup(prompt,callback)

Operates the same way as popupprompt(), but includes a
directory search window.

simplepopup(prompt,callback)

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.

"Shift_" is not used in conjunction with ASCII characters,
unless in combination with other modifiers.
e.g., "A" is used instead of "Shift_a", but
"Control_Shift_q" is used instead of "Control_Q".

Mouse buttons may be indicated as "Button1", "Button2",
and "Button3", respectively. Modifiers cannot be added
to buttons, although internally, xcircuit always treats
Shift_Button1 as Button2 for compatibility with systems
having only two-button mice.

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:

Polygons

dict =

{

"type"

:

"Polygon",

"color"

:

colorval,

"style"

:

styleval,

"linewidth"

:

widthval,

"points"

:

pointlist

}

Arcs

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

}

Paths

dict =

{

"type"

:

"Path",

"color"

:

colorval,

"style"

:

styleval,

"linewidth"

:

widthval,

"parts"

:

partslist

}

Labels

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:

intval

Any integer

floatval

Any floating-point value

stringval

Any normal (Python) string

colorval

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.

styleval

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.

justval

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.

pinval

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.

widthval

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

element

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).

stringdictpart

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

}

stringstringpart

Can be one of the following strings:

"End Parameter"

"Tab Stop"

"Tab Forward"

"Tab Backward"

"Return"

"Subscript"

"Superscript"

"Normalscript"

"Underline"

"Overline"

"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.

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"

"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).

"boundingbox"

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.

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).