This is the html version of the file http://starship.python.net/crew/da/freebie/freenum.pdf.
G o o g l e automatically generates html versions of documents as we crawl the web.
To link to or bookmark this page, use the following url: http://www.google.com/search?q=cache:UfgU7fHgAfYJ:starship.python.net/crew/da/freebie/freenum.pdf+PyArrayObject+C%2B%2B&hl=en&ie=UTF-8


Google is not affiliated with the authors of this page nor responsible for its content.
These search terms have been highlighted: pyarrayobject c++ 

An Overview of the Numeric Extensions to Python
Page 1
An Overview of the Numeric Extensions to Python - 7th Python Workshop - Houston TX - November 10, 1998 Numeric Python Tutorial - © 1998, David Ascher
An Overview of
The Numeric Extensions
to Python
7th International Python Workshop
November 10, 1998
Houston, TX
David Ascher
da@python.net
2
David Ascher
mailto:da@python.net
http://starship.skyport.net/~da
Python:
– Discovered Python (1.2) a few years ago.
– Taught it to friends and colleagues, and to a couple of
software companies.
– Designed and wrote commercial web/database software
entirely in Python.
– python-help@python.org
– Special interests:
OOP, numerical computation, graphics.
– Maintain PyOpenGL bindings
– Co-authored Learning Python w/ Mark Lutz @ ORA
– Consulting & Training
Science:
– Everyday user for computational modeling, data acquisition,
stimulus generation, etc.
– B.S. in Physics, Ph.D. in Cognitive Science, Brown Univ.
– I study visual perception, computational modeling of the
brain, neural networks.
– Research Fellow,
Smith-Kettlewell Eye Research Institute, S.F., CA.

Page 2
An Overview of the Numeric Extensions to Python - 7th Python Workshop - Houston TX - November 10, 1998 Numeric Python Tutorial - © 1998, David Ascher
3
Interrupt,
Interrupt,
Interrupt.
4
Outline
Prelude: What is Numeric Python?
– Numerical Computing in Python and Numeric Python
The new arrays
– Creation, Printing, Slicing, Shaping, Casting, etc.
– Array properties and attributes
– Gotcha's
Universal Functions
– Inventory
– Examples
– Gotcha's
Algorithmic operations on arrays
– Inventory of tools
– Thinking Globally
Extensions to NumPy
The C/C++ API

Page 3
An Overview of the Numeric Extensions to Python - 7th Python Workshop - Houston TX - November 10, 1998 Numeric Python Tutorial - © 1998, David Ascher
5
Math in Python
For sociological reasons, many users of Python are
scientists and engineers – wanted clean general purpose
language to steer computation. Needed a readable
language which knows about numbers, and can be
interfaced easily.
Perl:
not readable enough for many non-programmers
Tcl:
didn't deal well with large sets of numbers
Python:
BN (Before Numeric):
• Floats (doubles), Ints, Long Ints, math,
rand/whrand, rational numbers, etc.
• Arrays were either weak and 1D (the array module)
or very high overhead and cumbersome (classes
around lists of lists...)
AN (After Numeric):
• N-dimensional arrays of floats, ints, complex
numbers, etc.
Fast operations on these arrays
• Efficient operations on collections of like objects
6
Numbers in Python, BN
Before Numeric Extension:
– Floats (C doubles)
– Integers (C ints)
– Long integers (unlimited size)
– Classes that act like numbers
• Rational Numbers
• Complex Numbers
• etc.
– arrays are 1-Dimensional
– Multidimensional arrays are non-intuitive:
>>> x = [0]*5
>>> x[0] = 1
>>> print x
[1, 0, 0, 0, 0]
>>> x = [[0]*5]*5
>>> x[0][0] = 1
>>> print x
[[1, 0, 0, 0, 0], [1, 0, 0, 0, 0],
[1, 0, 0, 0, 0], [1, 0, 0, 0, 0],
[1, 0, 0, 0, 0]]

Page 4
An Overview of the Numeric Extensions to Python - 7th Python Workshop - Houston TX - November 10, 1998 Numeric Python Tutorial - © 1998, David Ascher
7
math module
The Usual Suspects:
acos (x)
asin (x)
atan (x)
atan2(x, y)
ceil (x)
cos (x)
cosh (x)
exp (x)
fabs (x)
floor (x) fmod (x, y)
frexp (x)
hypot (x, y)
ldexp (x, y) log (x)
log10 (x)
modf (x)
pow (x, y)
sin (x)
sinh (x)
sqrt (x)
tan (x)
tanh (x)
The module also defines two mathematical constants:
pi = 3.14159265359
e = 2.71828182846
8
array module
Allows the creation of “compact” arrays of a single type,
e.g. characters, signed integers, etc.
>>> import array
>>> x = array.array('i', [2,2,3])
>>> x.append(3)
# appends 3
>>> x.append(4.2)
# appends 4
>>> x.append('x')
# TypeError!
array.tofile(file) array.fromfile(f, n)
array.tostring() array.fromstring(s)
array.tolist() array.fromlist(l)
Supported typecodes are:
c: 1-byte character
b: 1-byte signed int
h,i: 2-byte signed int
l: 4-byte signed int
f: 4-byte float
d: 8-byte float
Not very useful within Python – mostly used to interact
with byte streams like sound files.

Page 5
An Overview of the Numeric Extensions to Python - 7th Python Workshop - Houston TX - November 10, 1998 Numeric Python Tutorial - © 1998, David Ascher
9
random & whrandom
modules
random.srand(seed):
initializes the random number generator
random.rand():
returns an integer between [0… 32768)
random.choice(s):
returns a random element from the sequence s.
whrandom.seed(x,y,z):
initializes whrandom number generator.
whrandom.random():
returns the next random floating point number in the
range [0.0...1.0)
Creating a million random numbers is very slow...
10
Numeric Python
Provides support for multidimensional homogeneous
arrays, and then some.
Written by Jim Hugunin at MIT, with support from the
Matrix-SIG and based on earlier work by Jim Fulton.
Taken over by LLNL.
ftp://ftp-icf.llnl.gov/pub/python
Users and functionality inspired by:
– FORTRAN
– APL
– J
– S+
– IDL
– MATLAB
– Mathematica
– Gauss
– Yorick
– Basis
– ...
But remember: Python is a general-purpose language.

Page 6
An Overview of the Numeric Extensions to Python - 7th Python Workshop - Houston TX - November 10, 1998 Numeric Python Tutorial - © 1998, David Ascher
11
Numbers in Python, AN
With Numeric Python:
– Complex numbers ( j is the imaginary unit) (since 1.4)
>>> x = 3 + 4j
>>> print x
(3+4j)
– Arrays of floats, integers and complex numbers of
various precisions.
– Multiple dimensions are easy and intuitive:
>>> a = zeros((5,5))
>>> a[0,0] = 1
>>> print a
[[1 0 0 0 0]
[0 0 0 0 0]
[0 0 0 0 0]
[0 0 0 0 0]
[0 0 0 0 0]]
– Operating on large sets of numbers is fast because it’s
done by the internals (C or Java)
12
Complex Math
cmath
module provides functions similar to those from the
math
module which know about complex numbers (e.g.
cmath.sqrt(-1) == 1j while math.sqrt(-1) raises an exception).
Like complex numbers, complex arrays have two attributes:
.
real
.
imag
which return their real and imaginary parts respectively
(
imaginary
is a synonym for
imag
for arrays only).
conjugate()
is a function which takes any number or array
and returns its complex conjugate.
cmath
is part of the core of Python.

Page 7
An Overview of the Numeric Extensions to Python - 7th Python Workshop - Houston TX - November 10, 1998 Numeric Python Tutorial - © 1998, David Ascher
13
What is Numeric
New Types:
¡ complex numbers (now in core)
¡ array (multidimensional)
¡ makes the old array module almost obsolete
New Functions:
¡ creating arrays
¡ manipulating arrays
New Modules:
¡ math replacement modules
• cmath (in core), umath
¡ Numeric:
• Provides core support
¡ RandomArray & friends.
• Very good random number generators
¡ FFT & friends
Interface to FFTPACK
¡ LinearAlgebra:
Interface to LAPACK
14
Creating Arrays
Always
import Numeric
>>> from Numeric import *
array()
takes a sequence as input,and returns an
array:
>>> a = array([1.2, 3.5, -1])
>>> print a
[1.2 , 3.5, -1.]
>>> print type(a)
<type ’array’>
– All the elements in the sequence are cast “up” to the
appropriate type – no unsafe casting allowed.
– The array cannot be sparse – it has to “fill” every
dimension.
Arrays can be multidimensional if the input sequences
are:
>>> a = array([[1.2, 3.5, -1],
... [0.2, 2, -2],
... [4.2, .5, -3]])
>>> print a
[[ 1.2, 3.5, -1.]
[ 0.2, 2., -2.]
[ 4.2, 0.5, -3.]]

Page 8
An Overview of the Numeric Extensions to Python - 7th Python Workshop - Houston TX - November 10, 1998 Numeric Python Tutorial - © 1998, David Ascher
15
Creating Constant Arrays
zeros(), ones()
>>> print zeros((5,5))
[[0 0 0 0 0]
[0 0 0 0 0]
[0 0 0 0 0]
[0 0 0 0 0]
[0 0 0 0 0]]
>>> print ones((4,2), Float)
[[ 1. 1.]
[ 1. 1.]
[ 1. 1.]
[ 1. 1.]]
First argument to zeros() and ones() is the shape,
second (optional) argument is the typecode (Int by
default).
16
Array Typecode
All elements in an array must have the same type,
defined by the array’s typecode:
>>> a = ones((1,2), Float)
>>> a.typecode()
'd'
Typecodes can be one of:
– Float, Float0, Float8, Float32, Float64
– Int, Int0, …8, …16, …32,
– Complex, …0, …16, …32, …64, …128
– PyObject
– Float0, Int0, Complex0 correspond to the smallest
possible sizes. Float8 is the smallest float with at least 8 bits,
Float16 that with at least 16 bits, etc.
– Float, Int, Complex correspond to the standard Python
datatypes (C double, C long int, two C doubles)
– Actual word length will depend on the platform.
– PyObject means “Python Object” – lose efficiency.
Note that
typecode()
is a method, to remind you that
it is immutable.

Page 9
An Overview of the Numeric Extensions to Python - 7th Python Workshop - Houston TX - November 10, 1998 Numeric Python Tutorial - © 1998, David Ascher
17
Array Shape
Arrays have shape, the arrangement of dimensions:
>>> a = array([1,2,3,4,5,6])
>>> a.shape
(6,)
– This a is a one-dimensional vector. Its rank is
len(a.shape) == 1
– Shape is a mutable attribute. It can be changed by
assigning to it:
>>> a.shape = (2,3)
>>> print a
[[1 2 3]
[4 5 6]]
>>> a.shape
(2, 3)
– New dimensions can be added with unit shape
elements:
>>> a.shape = (2,3,1)
>>> a.shape = a.shape + (1,)
>>> print a.shape
(2,3,1,1)
18
Changing Shape, con’t
One can also use the
reshape()
function:
>>> new_a = reshape(a, (4,5))
In either case, a single -1 means “however many
dimensions are left over: once the other dimensions are
taken care of”:
>>> print a.shape
(20,)
>>> a.shape = 4,-1
>>> print a.shape
(4,5)
>>> a.shape = 2,5,-1
>>> print a.shape
(2,5,2)

Page 10
An Overview of the Numeric Extensions to Python - 7th Python Workshop - Houston TX - November 10, 1998 Numeric Python Tutorial - © 1998, David Ascher
19
.flat & ravel()
The data in an array can be accessed by its
.flat
attribute, or through the ravel function:
>>> print a
[[1 2 3]
[4 5 6]]
>>> print a.flat
[1 2 3 4 5 6]
>>> print ravel(a)
[1 2 3 4 5 6]
.flat
is a read-only attribute, but its contents can be
modified:
>>> a.flat = range(6,12)
AttributeError: Attribute does not exist
or cannot be set
>>> a.flat[:] = range(6,12)
>>> print a
[[ 6 7 8]
[ 9 10 11]]
>>> a.flat[-1] = -1
>>> print a
[[ 6 7 8]
[ 9 10 -1]]
20
Note on Printing Arrays
Arrays are printed using the following algorithm:
– Last (outermost) dimension is printed
from left to right
– Next-to-last dimension is printed down
– Earlier dimensions printed with more []'s:
>>> x = array(range(8))
>>> print x
[0 1 2 3 4 5 6 7]
>>> x.shape = (2,4)
>>> print x
[[0 1 2 3]
[4 5 6 7]]
repr()
of an array return an
eval
’able string:
>>> x
array([[0, 1, 2, 3],
[4, 5, 6, 7]])
>>> y = eval(repr(x))
>>> type(y)
<type ’array’>
– compare to
str()

Page 11
An Overview of the Numeric Extensions to Python - 7th Python Workshop - Houston TX - November 10, 1998 Numeric Python Tutorial - © 1998, David Ascher
21
Customizing Printing
Can control things like precision of floating point numbers
>>> print x
[0 1 2]
>>> str(x)
'[0 1 2]'
>>> repr(x)
'array([0, 1, 2])' # note the array(...) and ,’s
>>> x = arange(0,.01,.001)
>>> print x
[ 0. 0.001 0.002 0.003 0.004 0.005 0.006 0.007
0.008 0.009]
>>> import sys
>>> sys.float_output_precision = 2
>>> print x
[ 0. 0. 0. 0. 0. 0.01 0.01 0.01 0.01
0.01]
And whether to display very small numbers:
>>> print x
[ 1.00000000e-005 3.14159265e+000]
>>> sys.float_output_suppress_small = 1
>>> sys.float_output_precision = 3
>>> print x
[ 0. 3.142]
22
arrayrange()
A very useful version of
range()
which produces
arrays. Also called
arange().
– By default works like array(range())
>>> arange(5)
array([0, 1, 2, 3, 4])
>>> arange(5,10)
array([5, 6, 7, 8, 9])
>>> print arange(5, 0, -1)
[5 4 3 2 1]
– Can yield floating point or complex arrays:
>>> arange(5.0)
array([0., 1., 2., 3., 4.])
>>> print arange(5, typecode=Complex)
[ 0.+0.j, 1.+0.j, 2.+0.j, 3.+0.j,
4.+0.j]
– Can have non-integer strides:
>>> arange(0,.5,.1)
array([0., 0.1, 0.2, 0.3, 0.4])

Page 12
An Overview of the Numeric Extensions to Python - 7th Python Workshop - Houston TX - November 10, 1998 Numeric Python Tutorial - © 1998, David Ascher
23
span()
Not part of Numeric, but so useful. Creates a range of N
floats given inclusive beginnings and ends:
isintorlong = lambda x: type(x) == type(0) or \
type(x) == type(0L)
def span(Min, Max, Num):
assert isintorlong(Num)
if isintorlong(Min) and isintorlong(Max) and \
(Max-Min) % (Num-1) != 0:
Max = float(Max) # force floating points
return Min+(Max-Min)*arange(Num)/(Num-1)
>>> print span(0,1,11)
[ 0. 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1. ]
>>> print span(10, 100, 10)
[ 10 20 30 40 50 60 70 80 90 100]
24
Indexing
Given:
>>> print a
[[ 1.2 3.5 -1. ]
[ 0.2 2. -2. ]
[ 4.2 0.5 -3. ]]
Multidimensional indexing is easy:
>>> print a[0,0]
1.2
The first index is that with the largest stride, so:
>>> print a[0,1]
3.5
>>> print a[1,0]
0.2
One can index rows:
>>> print a[0]
[ 1.2 3.5 -1. ]
One can index columns:
>>> print a[:,0]
[ 1.2 0.2 4.2]

Page 13
An Overview of the Numeric Extensions to Python - 7th Python Workshop - Houston TX - November 10, 1998 Numeric Python Tutorial - © 1998, David Ascher
25
0
1
2
3
[[ 0 1 2 3 4]
[ 5 6 7 8 9]
[10 11 12 13 14]
[15 16 17 18 19]
[20 21 22 23 24]]
Slices work as expected:
>>> print b[0:3, -3:-1]
[[ 2 3]
[ 7 8]
[12 13]]
Missing indices are assumed to be : (from beginning to end):
>>> print b[0] # equivalent to b[0,:]
[0 1 2 3 4]
>>> print b[:,-1]
[ 4 9 14 19 24]
There is an optional third stride argument to the slice
operator:
>>> x = arange(10)
>>> print x[9:0:-1]
[9 8 7 6 5 4 3 2 1]
>>> print x[::-2]
[9 7 5 3 1 ]
Slicing Arrays
-1
-2
-3
26
Ellipsis
Sometimes you want to skip over dimensions:
if:
>>> x.shape = (3,4,4,2)
then:
x[0,...,1] == x[0,:,:,1]
In other words ... is like : stretched to fill as many
dimensions as needed.
Only the first ... stretches, so that
x[...,0,...] == x[...,0,:]

Page 14
An Overview of the Numeric Extensions to Python - 7th Python Workshop - Houston TX - November 10, 1998 Numeric Python Tutorial - © 1998, David Ascher
27
slice(start, end, stride)
All Python syntactic operations should have functional
equivalents (witness the
operator
module).
The new syntax needed by slicing:
myArray[1:2:-1]
can be expressed using the new builtin
slice
:
>>> mySlice = slice(1, 2, -1)
>>> myArray[mySlice]
>>> operator.getitem(myArray, mySlice)
Default endpoints are obtained by using
None
:
[::]
<--->
slice(None,None,None)
[:2:-1] <--->
slice(None, 2, -1)
Consequence: It is now possible to use the :: powerslicer
in instances. Instead of a call to
__getslice__
,
__getitem__
is called with a
slice()
object.
28
WARNING
References By Default
Many functions of arrays (and slices!) return references
to the same data as the original:
>>> x = zeros(5)
>>> y = x[1:-1]
>>> print x, y
[0 0 0 0 0] [0 0 0]
>>> y[1] = 100
>>> print x, y
[ 0 0 100 0 0 ] [ 0 100 0 ]
The data is shared by the many array objects. This
saves space and time, but can be confusing.
To get a copy, you need to make a copy explicitly:
>>> z = array(x[1:-1], copy=1)
>>> z[0] = -1
>>> print x, y, z
[ 0 0 100 0 0] [ 0 100 0] [ -1 100 0]

Page 15
An Overview of the Numeric Extensions to Python - 7th Python Workshop - Houston TX - November 10, 1998 Numeric Python Tutorial - © 1998, David Ascher
29
Setting Values in an Array
>>> print myArray
[[ 0 1 2 3 4]
[ 5 6 7 8 9]
[10 11 12 13 14]
[15 16 17 18 19]
[20 21 22 23 24]]
Setting by indices works:
>>> myArray[0,3] = 1
Warning: the typecode will not change:
>>> myArray[0,0] = 1.222
>>> print myArray[0,0]
1
Standard Python numeric conversions allowed (no
complex a real, character a number, etc.).
30
Automatic Conversions
PyObject
Complex32
Complex64
Complex128
Float32
Float64
Float128
Float16
Float8
Char
Int32
Int64
Int128
Int16
Int8
UnsignedInt8
Different-type
coercion
Real numbers
N.B. Within the domain of real
numbers, casts "down" are
possible with asarray()
Same-type coercion

Page 16
An Overview of the Numeric Extensions to Python - 7th Python Workshop - Houston TX - November 10, 1998 Numeric Python Tutorial - © 1998, David Ascher
31
Setting Slices
Setting with slices works as well:
>>> myArray[2:4, 0] = (100,200)
>>> print myArray
[[ 0 1 2 3 4]
[ 5 6 7 8 9]
[100 11 12 13 14]
[200 16 17 18 19]
[ 20 21 22 23 24]]
If setting slices with lower-rank values, data are copied
(broadcast):
>>> myArray[0] = 1
>>> print myArray
[[ 1 1 1 1 1]
[ 5 6 7 8 9]
[100 11 12 13 14]
[200 16 17 18 19]
[ 20 21 22 23 24]]
32
Broadcasting
Arrays with the same shape can obviously be operated
on:
if a.shape == b.shape:
c = a * b
If the shapes don't match:
– If the dimensions where the mismatch occurs are 0
(absent) or 1, then broadcasting occurs:
>>> x = arange(10)
>>> print x * 2
[0 2 4 6 8 10 12 14 16 18]
>>> print x + array([2,])
[2 3 4 5 6 7 8 9 10 11]
– Otherwise, Python will complain:
>>> print x * array([4,5])
ValueError: frames are not aligned

Page 17
An Overview of the Numeric Extensions to Python - 7th Python Workshop - Houston TX - November 10, 1998 Numeric Python Tutorial - © 1998, David Ascher
33
but in linear algebra...
If one wants to do outer products of two rank-1 vectors:
>>> x = arange(5)
>>> y = arange(3)
>>> print x, y
[0 1 2 3 4] [0 1 2]
>>> print x.shape, y.shape
(5,) (3,)
One has to do:
>>> y.shape = (3,1)
>>> print y
[[0]
[1]
[2]]
>>> x * y
[[0 0 0 0 0]
[0 1 2 3 4]
[0 2 4 6 8]]
Quite cumbersome...
34
NewAxis to the rescue!
NewAxis
in a slice stands for “insert a new axis here,” so
that instead of:
c = a * reshape(b, (5, 1))
One can do:
c = a * b[:, NewAxis]
NewAxis
is especially useful when the new dimension is
only used in an intermediate computation.

Page 18
An Overview of the Numeric Extensions to Python - 7th Python Workshop - Houston TX - November 10, 1998 Numeric Python Tutorial - © 1998, David Ascher
35
So far, arrays:
– Have a typecode (immutable)
– Have a shape (mutable)
– Have elements (mutable)
– Can be sliced and diced.
So what?
The point of arrays is to do operations on large numbers
of elements at a time, fast and easily.
This is done using ufuncs.
36
Element-wise Operations
All the standard operators work with arrays, element-
wise.
>>> print myArray
[[ 0 1 2 3 4 5]
[ 6 7 8 9 10 11]]
>>> print myArray + myArray
[[ 0 2 4 6 8 10]
[12 14 16 18 20 22]]
>>> print -myArray
[[ 0 -1 -2 -3 -4 -5]
[ -6 -7 -8 -9 -10 -11]]
>>> print myArray * myArray
[[ 0 1 4 9 16 25]
[ 36 49 64 81 100 121]]
Important: * is not matrix multiplication. It is
elementwise array mutliplication.

Page 19
An Overview of the Numeric Extensions to Python - 7th Python Workshop - Houston TX - November 10, 1998 Numeric Python Tutorial - © 1998, David Ascher
37
Umath module
The
umath
module defines ufuncs corresponding to
most of the functions of the
math
module, but they work
en masse on all the elements of an array. In fact, they'll
work on any sequence and return an array:
>>> umath.sin([1,2,3])
array([ 0.84147098, 0.90929743, 0.14112001])
When doing
from Numeric import *
, the umath
module functions are loaded automatically.
absolute arccos arcsin arctan arctan2
ceil conjugate cos cosh divide exp
fabs floor fmod hypot invert left_shift log
log10 multiply negative power remainder
right_shift sin sinh sqrt subtract tan tanh
These are joined by
add
subtract
divide
remainder
multiply
38
Ufuncs
Ufuncs are "Universal Functions". They are:
– Callable (with sequences and arrays)
– They have methods which are themselves callable.
Ufuncs are called thus because they work on any Python
sequences (tuples, lists, etc.)
>>> import Numeric
>>> Numeric.add.reduce(dir())
'Numeric__builtins____doc____name__'
>>> add.reduce(map(len, dir()))
45

Page 20
An Overview of the Numeric Extensions to Python - 7th Python Workshop - Houston TX - November 10, 1998 Numeric Python Tutorial - © 1998, David Ascher
39
Ufuncs, con't
One can also call their methods (
reduce, accumulate,
outer
):
>>> print x, y
[0 1 2 3 4] [3 2 1 2 4]
>>> import umath
>>> umath.add.reduce(x)
10
>>> from umath import *
>>> print add.accumulate(y)
[ 3 5 6 8 12]
>>> print add.outer(x,y)
[[3 2 1 2 4]
[4 3 2 3 5]
[5 4 3 4 6]
[6 5 4 5 7]
[7 6 5 6 8]]
40
Ufuncs, con't
Given multidimensional arrays, one can choose the axis
of, e.g., reduction:
>>> x = reshape(arange(16), (4,4))
>>> print x
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]
[12 13 14 15]]
>>> print add.reduce(x,0)
[24 28 32 36]
>>> print add.reduce(x,1)
[ 6 22 38 54]

Page 21
An Overview of the Numeric Extensions to Python - 7th Python Workshop - Houston TX - November 10, 1998 Numeric Python Tutorial - © 1998, David Ascher
41
Ufunc gotcha!
Ufuncs have an optional extra argument, which is an
“output array”. To add arrays “in place”, one can do:
add(op1,op2,op1)
Unary ufuncs take an optional second argument which
is the output array. Thus x = abs(x) translates to:
absolute(x, x)
Beware of nasty surprises when manipulating non-
contiguous arrays or other non-trivial stride arrays:
>>> a = arange(10)
>>> print add(a[::-1], a, a)
[ 9 9 9 9 9 14 15 16 17 18]
42
Comparisons fail for now
Comparisons of arrays raises exceptions (except when
they are the same object).
Comparisons of arrays will (probably!) return arrays of
0's and 1's, so that one could do:
myarray[myarray > 100] = 100
But not just yet.
How to do this? Use algorithmic functions (more later).

Page 22
An Overview of the Numeric Extensions to Python - 7th Python Workshop - Houston TX - November 10, 1998 Numeric Python Tutorial - © 1998, David Ascher
43
Comparison Ufuncs
A set of other
ufuncs
is defined in
umath
:
– greater, greater_equal
– less, less_equal
– equal, not_equal
– bitwise_and, bitwise_or, bitwise_xor
– logical_and, logical_or, logical_xor,
logical_not
– maximum, minimum
These can be called, and work like you'd expect:
>>> x = arange(5)
>>> y = array([3,2,1,2,4])
>>> print x, y
[0 1 2 3 4] [3 2 1 2 4]
>>> print greater(x, y)
[0 0 1 1 0]
>>> print bitwise_and(x,y)
[0 0 0 2 4]
>>> print logical_and(x,y)
[0 1 1 1 1]
44
fromfunction
Given:
def myFunc(x,y):
return (x-4)**2 + (y-4)**2
The very slow:
myData = zeros((10,10), ’f’)
for x in range(10):
for y in range(10):
myData[x,y] = myFunc(x,y)
can be replaced by:
>>> myData = fromfunction(myFunc, (8,8))
>>> print myData
[[32 25 20 17 16 17 20 25]
[25 18 13 10 9 10 13 18]
[20 13 8 5 4 5 8 13]
[17 10 5 2 1 2 5 10]
[16 9 4 1 0 1 4 9]
[17 10 5 2 1 2 5 10]
[20 13 8 5 4 5 8 13]
[25 18 13 10 9 10 13 18]]
CAUTION:
– fromfunction needs to use all of its arguments:
def myFunc(x,y): return x # will not work
– the function must only consist of basic operations and
ufuncs (no ifs or chooses).

Page 23
An Overview of the Numeric Extensions to Python - 7th Python Workshop - Houston TX - November 10, 1998 Numeric Python Tutorial - © 1998, David Ascher
45
Writing Versatile Code
How can one write code which works both with arrays
and with numbers?
Problems:
– ufuncs and functions in math aren't the same (e.g. pow vs.
power)
– Can't treat numbers as arrays and vice-versa
One solution:
def myfunc(input, ...):
inputType , input = makeArray (input)
...
# do the math on arrays
...
return makeOutput (output, inputType )
46
makeArray and makeOutput
from Numeric import ArrayType
from Types import *
def makeArray(input):
if isinstance(input, ArrayType):
return ArrayType, input
if isinstance(input, ListType):
return ListType, array(input)
if isinstance(input, TupleType):
return TupleType, array(input)
return type(input), array(input)
def makeOutput(output, outputType):
if outputType == ArrayType:
return output
if outputType == ListType:
return output.tolist()
if outputType == TupleType:
return tuple(output.tolist()) # inc.
return output[0] #
Customize these to your needs. There is no "right"
solution.

Page 24
An Overview of the Numeric Extensions to Python - 7th Python Workshop - Houston TX - November 10, 1998 Numeric Python Tutorial - © 1998, David Ascher
47
Automatic compilation?
Function calls in Python are expensive. Thus iterative
and otherwise not-massively computed operations are
quite slow.
Hope that one could automate the process of converting
from Python code to C/C++ code. Still elusive.
Many tough issues:
– Parsing of bytecode
– Knowing what to aim for (not all Python!)
– Portable interface to Make/C/C++/dynamic loading
– Inability to reload dynloadable modules
48
Up-casting Gotcha!
To save memory (at the cost of precision), one can use
'small' arrays:
>>> x = arange(10)
>>> x.itemsize()
4
# 4 bytes/element
>>> x = x.astype('b')
>>> x
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9],'b')
>>> x.itemsize()
1
# 1 byte/element
But this is fragile:
>>> y = x * 2
>>> y.typecode(), y.itemsize()
('i', 4) # 4 bytes/element!!

Page 25
An Overview of the Numeric Extensions to Python - 7th Python Workshop - Houston TX - November 10, 1998 Numeric Python Tutorial - © 1998, David Ascher
49
Up-casting Solution
Need to convert Python numbers to 'small' arrays as
well:
>>> y = x * array(2, 'b')
>>> y.typecode(), y.itemsize()
('b', 1)
Made easier w/ the following:
Byte = lambda x: array(x, 'b')
Short = lambda x: array(x, 's')
Long = lambda x: array(x, 'l')
Float = lambda x: array(x, 'f')
Double = lambda x: array(x, 'd')
def SameSizeAs(input, ref):
return array(input, ref.typecode())
y = x * Byte(2)
or
y = x * SameSizeAs(2, x)
50
Gotcha! Arrays of Strings
Arrays of Python objects can be useful (for slicing, taking,
etc.)
array(...sequences..., ’O’)
However, strings, tuples, etc. are sequences and are
automatically ‘unpacked’. Sometimes that’s not what’s
intended:
>>> x = array((’john’, ’joe’))
>>> print x.typecode(), x.shape, x[0,0]
c (2, 4) j
>>> print x
[[j o h n]
[j o e ]]
>>> y = array((’john’, ’joe’), ’O’)
>>> print y.typecode(), y.shape, y[0,0]
O (2, 4) john
>>> print y
[[john john john john ]
[joe joe joe joe ]]
Solution: preshape arrays of PyObjects:
>>> z = zeros(2, PyObject)
>>> z[:] = (’john’, ’joe’)
>>> print z.typecode(), z.shape, z[0]
O (2,) john

Page 26
An Overview of the Numeric Extensions to Python - 7th Python Workshop - Houston TX - November 10, 1998 Numeric Python Tutorial - © 1998, David Ascher
51
A Case Study
My work involves designing and testing
computational models of neural function.
– Have functional forms, need to compare with
experimental data.
– Various limits on parameters
– Interested in understanding the effect of
parameters, more than just 'fitting'.
Needed tool to
– Explore parameter spaces of functions
– Visualize data in various ways
– Fast update of function parameters
– Fast display of results
52
Input

Page 27
An Overview of the Numeric Extensions to Python - 7th Python Workshop - Houston TX - November 10, 1998 Numeric Python Tutorial - © 1998, David Ascher
53
Output
54
Moral of that story
1) NumPy is fast enough to do interactive math.
2) Python is rich enough to allow:
– GUI
– Dynamic creation of widgets based on function objects
– Wrappers around function objects
– Threaded parallelism
– Extreme versatility
– all in very few lines.
3) I'd never think of writing this in
– C, C++
– Java
– MATLAB, Mathematica
– IDL, FORTRAN
– Visual Basic
– etc.
4) Caveat: Real need to write from scratch things
which some of those other tools provide.
“On n’est jamais si bien servi que par soi-même.”

Page 28
An Overview of the Numeric Extensions to Python - 7th Python Workshop - Houston TX - November 10, 1998 Numeric Python Tutorial - © 1998, David Ascher
55
Break
Back here in 15 minutes.
Feel free to ask me questions.
56
Part II: Fancy stuff
Selection Operations
– where , choose
– nonzero, compress
– repeat, take
Utility Functions
– identity, trace, diagonal
– reshape & resize
– transpose & swapaxes
– concatenate
– sort, argsort
The APIs
– C
– CXX
NumPy Extensions
– RandomArray
– FFT
– dot, Matrix class, LinearAlgebra

Page 29
An Overview of the Numeric Extensions to Python - 7th Python Workshop - Houston TX - November 10, 1998 Numeric Python Tutorial - © 1998, David Ascher
57
Question: Flow of control
Much code looks like this in non-array languages:
for i in i_indices:
for j in j_indices:
for k in k_indices:
m3[i,j,k] = m1[i,j,k] + m2[i,j,k]
Can be written in array languages as:
m3 = m1 + m2
What about:
for ...
if m1[i,j,k] > m2[i,j,k]:
m3[i,j,k] = m1[i,j,k]
else:
m3[i,j,k] = m2[i,j,k] - abs(m1[i,j,k])
In other words, how does one do control flow array-
wise?
58
Answer: make logic explicit
if m1[i,j,k] > m2[i,j,k]:
m3[i,j,k] = m1[i,j,k]
else:
m3[i,j,k] = m2[i,j,k] - abs(m1[i,j,k])
An
if
statement results in a logical result (0 or 1).
The comparison ufuncs can be used:
m1_gt_m2 = greater(m1, m2)
Then use the
where()
function:
m3 = where(m1_gt_m2, m2-abs(m1), m1)
where(condition, x, y)
returns an array shaped like the input
arrays with values from
x
and
y
depending on the values in
condition
Warning: the logical truth comes second...
.
0 0 0
1
0
0
1
0
1
1 2 3
4
7
5
8
6
9
5 5 5
2
5
2
5
2
5
1 2 3
2
7
5
5
6
5
where()

Page 30
An Overview of the Numeric Extensions to Python - 7th Python Workshop - Houston TX - November 10, 1998 Numeric Python Tutorial - © 1998, David Ascher
59
choose()
When the selection is based on an array index rather
than a logical fact, use
choose()
.
choose(choice_array,
(choice0, choice1, ... choiceN-1))
0 0 0
1
0
2
1
3
1
1 2 3
5
7
2
5
6
5
5
6
6
6 6
6
6
6 6
6
2 2 2
2
2
2
2
2
2
5 5 5
5
5
5
5
5
5
1 2 3
4
7
5
8
6
9
1
0
2
3
choose()
60
choose() example
Assume a is an array that you want to "clip" so that no
values are greater than 100.0.
>>> choose(greater(a, 100.0), (a, 100.0))
Everywhere that
greater(a, 100.0)
is false (i.e.. 0)
this will “choose” the corresponding value in a.
Everywhere else it will “choose”
100.0
.
More generally:
clip(m, m_min, m_max)
returns the data in
m
clipped
by the bounds
m_min
and
m_max
:
def clip(m, m_min, m_max):
selector = less(m, m_min)+2*greater(m, m_max)
return choose(selector, (m, m_min, m_max))

Page 31
An Overview of the Numeric Extensions to Python - 7th Python Workshop - Houston TX - November 10, 1998 Numeric Python Tutorial - © 1998, David Ascher
61
repeat(a, repeats, axis=0)
repeat()
takes an array and returns an array with each
element in the input array repeated as often as indicated
in the corresponding elements of the second array:
def sumofsquares(n): #
OneToN = arange(1, 1+n)
return add.reduce(repeat(OneToN, OneToN))
OneToN ---> [1 2 3 4 5]
repeat(OneToN, OneToN) --->
[1 2 2 3 3 3 4 4 4 4 5 5 5 5 5]
add.reduce(…) ---> 55
Useful for selecting subset of an array:
repeat(temp, logical_and(greater(temp, 280),
less(reflec, 0.10)))
(temperatures greater than 280 where the
reflectivity is less than 0.1)
62
take(a, indices, axis=0)
take()
selects the elements of the array it gets as first
argument based on the indices it gets as a second
argument.
>>> print a
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]
[12 13 14 15]]
>>> print take(a, (0,)) # first row
[[0 1 2 3]]
>>> print take(a, (0,1)) # first and second rows
[[0 1 2 3]
[4 5 6 7]]
>>> print take(a, (0,-1)) # first and last rows
[[ 0 1 2 3]
[12 13 14 15]]
Third argument specifies which axes to use
(defaults to 0, i.e. rows. Set it to 1 for columns, etc.)

Page 32
An Overview of the Numeric Extensions to Python - 7th Python Workshop - Houston TX - November 10, 1998 Numeric Python Tutorial - © 1998, David Ascher
63
take, con’t
If the indices to
take
are multidimensional, then the
result is a multidimensional array as well.
>>> x = arange(10) * 100
>>> print take(x, [[2,4],[1,2]])
[[200 400]
[100 200]]
Common uses of take include:
– Translation tables: Assume a gamma correction table for
pixels: 256 long, gives values between 0 and 256.
gamma_correction[orig_val] = gamma_val
corrected_pix = take(gamma_correction, pix )
– Sorting: If
a
is a rank-2 array with
a[0]
the evaluation
points and
a[1]
the values of a function at those points.
You can sort by the evaluation points by doing:
take(a, argsort(a[0]), 1)
64
nonzero(), compress()
nonzero(a):
returns an array containing the indices of the
elements in a that are nonzero. These indices only make sense
for 1d arrays, so the function refuses to act on anything else.
def nonzero(a):
repeat(arange(len(a)), not_equal(a, 0))
a ---> [0 0 2 0 0 6 7]
not_equal(a,0) ---> [0 0 1 0 0 1 1]
arange(len(a)) ---> [0 1 2 3 4 5 6]
repeat(...) ---> [2 5 6]
compress(condition, a):
those elements of a
corresponding to those elements of condition that are “true”.
def compress(condition, a, dim=-1):
return take(a, nonzero(condition), dim)
a ---> [9 8 7 6 5 4 3]
condition ---> [0 0 1 1 0 1 0]
nonzero(condition) ---> [2 3 5]
take(...) ---> [7 6 4]
compress(not_equal(0,a), a): the non-null
elements of a.

Page 33
An Overview of the Numeric Extensions to Python - 7th Python Workshop - Houston TX - November 10, 1998 Numeric Python Tutorial - © 1998, David Ascher
65
reshape()
reshape(a, shape)
returns an array with the same
data as a but a different shape. Shape is a tuple giving
the size of each dimension:
>>> x = arange(16)
>>> x.shape
(16,)
>>> print reshape(x, (2,8))
[[ 0 1 2 3 4 5 6 7]
[ 8 9 10 11 12 13 14 15]]
>>> print reshape(x, (4,4))
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]
[12 13 14 15]]
A dimension of
-1
means "whatever is needed":
>>> print reshape(x, (8,-1))
[[ 0 1]
[ 2 3]
[ 4 5]
[ 6 7]
...
Remember, a one-tuple is written
(x,)
.
66
resize() & identity()
resize(a, shape)
takes an array and returns an array
with the given shape and the same contents as the
original array, truncated or duplicated if necessary:
>>> print a
[0 1 2 3 4]
>>> print resize(a, (4,))
[0 1 2 3]
>>> print resize(a, (15,))
[0 1 2 3 4 0 1 2 3 4 0 1 2 3 4]
Useful trick:
def identity(n):
return resize([1]+n*[0], (n,n))
>>> print identity(10)
[[1 0 0 0 0 0 0 0 0 0]
[0 1 0 0 0 0 0 0 0 0]
[0 0 1 0 0 0 0 0 0 0]
[0 0 0 1 0 0 0 0 0 0]
[0 0 0 0 1 0 0 0 0 0]
[0 0 0 0 0 1 0 0 0 0]
[0 0 0 0 0 0 1 0 0 0]
[0 0 0 0 0 0 0 1 0 0]
[0 0 0 0 0 0 0 0 1 0]
[0 0 0 0 0 0 0 0 0 1]]

Page 34
An Overview of the Numeric Extensions to Python - 7th Python Workshop - Houston TX - November 10, 1998 Numeric Python Tutorial - © 1998, David Ascher
67
concatenate((a0,..., an), axis=0)
All input arrays will be concatenated along the given axis.
They must have the same shape along every axis except the
one given.
>>> print x
>>> print y
[[ 0 1 2 3]
[[20 21 22 23]
[ 4 5 6 7]
[24 25 26 27]
[ 8 9 10 11]]
[28 29 30 31]]
>>> print concatenate((x,y))
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]
[20 21 22 23]
[24 25 26 27]
[28 29 30 31]]
>>> print concatenate((x,y), 1)
[[ 0 1 2 3 20 21 22 23]
[ 4 5 6 7 24 25 26 27]
[ 8 9 10 11 28 29 30 31]]
To concatenate along a new axis, use
array()
>>> print array((x,y))
[[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
[[20 21 22 23]
[24 25 26 27]
[28 29 30 31]]]
68
transpose(x, axes)
transpose()
takes an array and returns a new array
which corresponds to a with the order of axes specified
by the second argument.
The default corresponds to flipping the order of all the
axes (equivalent to
arange(len(a.shape))[::-1]
).
>>> print x
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]
[12 13 14 15]]
>>> print transpose(x)
[[ 0 4 8 12]
[ 1 5 9 13]
[ 2 6 10 14]
[ 3 7 11 15]]
# equivalent to transpose(x, (1,0))

Page 35
An Overview of the Numeric Extensions to Python - 7th Python Workshop - Houston TX - November 10, 1998 Numeric Python Tutorial - © 1998, David Ascher
69
diagonal(a,k)
returns the entries along the kth
diagonal of a.
k is an offset from the main diagonal.
>>> print a
[[ 0 1 2 3 4]
[ 5 6 7 8 9]
[10 11 12 13 14]
[15 16 17 18 19]
[20 21 22 23 24]]
>>> print diagonal(a)
[ 0 6 12 18 24]
>>> print diagonal(a,1)
[ 1 7 13 19]
>>> print diagonal(a,-1)
[ 5 11 17 23]
trace()
returns the trace of a two-D array.
def trace(a, offset=0, axis1=0, axis2=1):
return add.reduce(
diagonal(a, offset, axis1, axis2))
diagonal()
k = 0
k = 1
70
argmax(a, axis=-1), argmin()
argmax()
returns an array with the indices of the
maximum values of its input array a along the given axis
(last one by default):
>>> print a
[[ 0 1 2 3 4]
[ 5 -2 20 8 9]
[ 10 11 12 13 14]
[-10 16 88 18 19]
[ 20 98 22 23 24]]
>>> print argmax(a)
[4 2 4 2 1]
>>> print argmax(a,0)
[4 4 3 4 4]
>>> print argmin(a)
[0 1 0 0 0]
>>> print argmin(a,0)
[3 1 0 0 0]
>>> print argmin(a,1)
[0 1 0 0 0]

Page 36
An Overview of the Numeric Extensions to Python - 7th Python Workshop - Houston TX - November 10, 1998 Numeric Python Tutorial - © 1998, David Ascher
71
searchsorted(a, values)
searchsorted
will return the indices of the positions
in
a
after which the
values
would be inserted
.
a
should be a rank-1 array sorted in ascending order.
>>> print a
[0 1 2 3 4 5 6 7 8 9]
>>> print searchsorted(a, (4.4, 2.3, 1.2, 9.9))
[4 2 1 9]
Especially useful for doing histograms:
def histogram(a, bins):
n = searchsorted(sort(a), bins)
n = concatenate([n, [len(a)]])
return n[1:]-n[:-1]
>>> print histogram([0,0,0,0,0,0,0,.33,.33,.33],
arange(0,1.0,.1))
[7 0 0 3 0 0 0 0 0 0]
72
sort(a, axis=-1)
sort
returns a copy of the elements of
a
sorted along
the given axis. The new array has the same shape, and
each axis is sorted in ascending order.
>>> print z
[[ 0 84 90]
[ 14 -75 -95]
[-27 65 98]
[ 41 -54 -99]]
>>> print sort(z)
[[ 0 84 90]
[-95 -75 14]
[-27 65 98]
[-99 -54 41]]
>>> print sort(z, 0)
[[-27 -75 -99]
[ 0 -54 -95]
[ 14 65 90]
[ 41 84 98]]
For contiguous arrays:
z.flat[:] = sort(z.flat)

Page 37
An Overview of the Numeric Extensions to Python - 7th Python Workshop - Houston TX - November 10, 1998 Numeric Python Tutorial - © 1998, David Ascher
73
argsort(a, axis=-1)
argsort
returns the indices of a needed to produce the
sorted array using
take(a, argsort(a)) .
This is useful to sort an array based on another one:
Given three arrays,
SubjectName, SubjectId
, and
Score
, one can do:
>>> print subjectId
[1000 1001 1002 1003 1004 1005 1006 1007 1008 1009]
>>> print Names
[john mary paul ahmed zoe zoltan abel spenser david guido ]
>>> print scores
[ 5. 2. 3. 5.5 9. 4.2 4.5 2.2 8. 9.9]
>>> decreasingScores = argsort(scores)[::-1]
>>> print take(subjectId, decreasingScores)
[1009 1004 1008 1003 1000 1006 1005 1002 1007 1001]
>>> print take(Names, decreasingScores)
[guido zoe david ahmed john abel zoltan paul spenser mary ]
74
.astype() & .itemsize()
a.astype(typecode):
Returns a copy of a with the specified typecode. The cast
can lose precision:
>>> x = array([1.2, 3.4, 5.6])
>>> x.typecode()
'd'
>>> y = x.astype(Int)
>>> print x
[1.2 3.4 5.6]
>>> print y
[1 3 5]
Overflow can cause problems:
>>> print x
[500 501 502 503 504]
>>> print x.astype(Int8)
[-12 -11 -10 -9 -8]
a.itemsize()
Returns the number of bytes used by any one element:
>>> x = array([1.2, 3.4, 5.6])
>>> x.itemsize()
8
>>> x = array([1.2, 3.4, 5.6], Float16)
>>> x.itemsize()
4

Page 38
An Overview of the Numeric Extensions to Python - 7th Python Workshop - Houston TX - November 10, 1998 Numeric Python Tutorial - © 1998, David Ascher
75
dot()
dot()
returns the dot product of two two-dimensional
arrays (matrices).
>>> print x
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]
[12 13 14 15]]
>>> print y
[[16 17 18 19]
[20 21 22 23]
[24 25 26 27]
[28 29 30 31]]
>>> print x * y
[[ 0 17 36 57]
[ 80 105 132 161]
[192 225 260 297]
[336 377 420 465]]
>>> print dot(x,y)
[[ 152 158 164 170]
[ 504 526 548 570]
[ 856 894 932 970]
[1208 1262 1316 1370]]
76
Structural vs. Non-Structural
Operations
Structural operations return arrays which depend only
on the structure of the array, not on the content.
– Examples:
transpose(), ravel(), slicing, etc.
– These operations always return references to the same
data (and use very little memory, and are fast).
Non-Structural operations return arrays whose
content depends on the content on the input arrays.
– Examples:
compress(), repeat(), choose(), etc.
– These operations return copies of the data.
To force a copy, use the
array
constructor with the
copy=1
argument:
>>> x = arange(10)
>>> y = array(x, copy=1)

Page 39
An Overview of the Numeric Extensions to Python - 7th Python Workshop - Houston TX - November 10, 1998 Numeric Python Tutorial - © 1998, David Ascher
77
Thinking Numerically
The trick is to go from:
if x > 0:
z = y + 3.0
else:
z = sin(y)
to:
z = choose(greater(x, 0), (sin(y), y+3.0))
What can’t be optimized easily:
– Recursive answer-dependent functions (e.g. if not all
cells in an array undergo the same number of operations.
– Complicated functions with lots of intermediate
variables on very large arrays (each intermediate
variable will result in an intermediate array – those can
get pretty big).
– Take those to C (C++, Java, whatever)
78
What's left to cover:
Distributions:
– Source (Unix and Win32):
ftp://ftp-icf.llnl.gov/
pub/python/LLNLPython.tgz
– Binary (Win32):
ftp://ftp-icf.llnl.gov/pub/python/NumPy.exe
– Mac :
mailto:just@letterror.com (Just van Rossum)
mailto:jack@cwi.nl (Jack Jansen)
Extensions to NumPy
– Shipped w/ NumPy
– Shipped w/ LLNLDistribution
– Elsewhere
Extending NumPy
– with C
– with C++ (CXX)
Documentation
NumPy and JPython

Page 40
An Overview of the Numeric Extensions to Python - 7th Python Workshop - Houston TX - November 10, 1998 Numeric Python Tutorial - © 1998, David Ascher
79
Extensions To NumPy
Fourier Transforms:
– FFT.py (w/ FFTPACK) -- in LLNL Distribution
fft(a, n=None, axis=-1)
inverse_fft(a, n=None, axis=-1)
real_fft(a, n=None, axis=-1)
inverse_real_fft(a, n=None, axis=-1)
fft2d(a, s=None, axis=(-2,-1))
real_fft2d(a, s=None, axis=(-2,-1))
– FFTW (Fastest Fourier Transform in the West)
http://starship.skyport.net/~da/Travis/fftw/
Linear Algebra Tools:
– LinearAlgebra.py (w/ LAPACK) -- in LLNL Distribution
solve_linear_equations(a,b)
inverse(a)
eigenvalues(a)
eigenvectors(a)
singular_value_decomposition(a)
generalized_inverse(a)
determinant(a)
linear_least_squares(a, b, rcond=1.e-10)
80
Random Numbers
RandomArray.py (w/ RANLIB
) (part of NumPy)
seed(x,y):
• Set the seeds
random(shape)
• Create an array filled with random floats between
[0.0,1.0) of the specified shape
uniform(min, max, shape)
• Create an array filled with random floats between
[min,max) of the specified shape
randint(min, max, shape)
• Create an array filled with random ints between
[min,max) of the specified shape
permutation(n)
• Create an array containing a random permutation
of the integers in [0,n)
RNG
(part of LLNL Distribution)
– Uniform, Normal, LogNormal distributions
rv
@
http://starship.skyport.net/crew/statistics/
– Many distributions (beta, Cauchy, chi_square,
Fisher_F, etc.), but not NumPy-based (slow).

Page 41
An Overview of the Numeric Extensions to Python - 7th Python Workshop - Houston TX - November 10, 1998 Numeric Python Tutorial - © 1998, David Ascher
81
Data Storage & Misc.
Array storage in standard formats:
– pickle
– 3 interfaces to NetCDF
http://www.yi.com/home/HinsenKonrad/netcdf.html
http://snow.cit.cornell.edu/noon/ncmodule.html
http://www.geog.ubc.ca/~kschalm
– Interface to PDB
(part of LLNL Distribution)
– To my knowledge, no interface to HDF.
Array I/O
– TableIO
http://www.npl.uiuc.edu/~miller/python/
– FortranFormat.py
http://starship.skyport.net/crew/hinsen/
FortranFormat.py
– numpyio
http://starship.skyport.net/~da/Travis/numpyio/
Others:
– PySimplex: Linear programming tools:
http://www.pythonpros.com/arw/pysimplex/
– Misc. Scientific Modules:
http://starship.skyport.net/~hinsen/
scientific.html
82
Graphics
The nice thing about standards...
Interfaces to Plotting Programs:
– Gist
– PGPLOT
– PLPLOT
– DISLIN
– GNUPLOT
– Gnu PlotUtils
Interfaces to Image Processing Toolkits:
– PIL
– Khoros
– GD (GIF)
Interfaces to 3D rendering/visualization libraries
– PyOpenGL (OpenGL/MESA)
– VTK
Interfaces to GUI's:
– Tk, WxPython, MFC, etc.
Other projects:
– Konrad's TkPlotCanvas
– my plotting framework (not even alpha)
See:
http://www.python.org/topics/scicomp/plotting.html

Page 42
An Overview of the Numeric Extensions to Python - 7th Python Workshop - Houston TX - November 10, 1998 Numeric Python Tutorial - © 1998, David Ascher
83
E.g.: Interfacing w/ PIL
For greyscale images:
def ArrayToImage(a):
i = Image.new("L", (a.shape[1], a.shape[0]))
i._fromstring(a.tostring())
return i
def ImageToArray(i):
a = fromstring(i.tostring(), 'b')
a.shape = i.im.size[1], i.im.size[0]
return a
.tostring()
/
fromstring(...)
:
raw data, w/o shape or typecode information.
84
UserArray and Matrix classes
UserArray
– Class version of array, supports indexing, slicing,
subclassing, etc.
– Doesn’t work as well with builtins (
take
, etc) as it
should.
– Unclear how builtins should deal with subclasses of
UserArray
...
Matrix
– a subclass of UserArray designed for linear algebra.
– Matrix multiplication is that of linear algebra, instead
of element-wise multiplication.
Hopefully these issues will get easier in the future with
an eventual merging of the object hierachy and the class
hierarchies and/or protocol support (see Developer Day
topics).

Page 43
An Overview of the Numeric Extensions to Python - 7th Python Workshop - Houston TX - November 10, 1998 Numeric Python Tutorial - © 1998, David Ascher
85
Writing a NumPy
extension module
...
#include "arrayobject.h"
Always start the module's init function with:
...
import_array();
Standard C extending techniques apply. Arrays are
PyArrayObject *
's.
86
PyArrayObject structure
typedef struct {
PyObject_HEAD
char *data;
# the numbers
int nd;
# the number of dimensions (rank)
int *dimensions, # the size of each dimension
*strides; # the stride along each dimension
PyObject *base; # [junk]
PyArray_Descr *descr; # typecode
int flags; # whether contiguous or not
} PyArrayObject;
For typecodes, see PyArray_TYPES in arrayobject.h:
enum PyArray_TYPES { PyArray_CHAR, PyArray_UBYTE,
PyArray_SBYTE, PyArray_SHORT,
PyArray_INT, PyArray_LONG,
PyArray_FLOAT, PyArray_DOUBLE,
PyArray_CFLOAT, PyArray_CDOUBLE,
PyArray_OBJECT, PyArray_NTYPES,
PyArray_NOTYPE};

Page 44
An Overview of the Numeric Extensions to Python - 7th Python Workshop - Houston TX - November 10, 1998 Numeric Python Tutorial - © 1998, David Ascher
87
arrayobject.h
int
PyArray_SIZE (PyArrayObject *the_array)
--> return size of array data in # of elements
int
PyArray_NBYTES (PyArrayObject *the_array)
--> return size of data area in bytes
PyArrayObject *
PyArray_FromDims (int n_dimensions,
int dimentions[n_dimensions],
int item_type) # e.g. PyArray_INT
--> return shaped array filled w/ NULLs. (aka 0's)
PyArrayObject *
PyArray_FromDimsAndData (int n_dimensions,
int dimentions[n_dimensions],
int item_type, # e.g. PyArray_INT
char *old_data
--> return shaped array filled w/ NULLs. (aka 0's)
PyArrayObject *
PyArray_ContiguousFromObject (PyObject *object,
int typecode,
int min_dimensions,
int max_dimensions,
--> return shaped array filled w/ contents of object
PyArray_CopyFromObject (...) # guarantees a copy
88
CXX
CXX is a great C++ tool for writing Python extensions.
Written by Paul Dubois @ LLNL
Nice Python-like C++ wrappers around most Python
objects.
Exception-handling passes between C++ and Python.
STL usable with Python container objects.
Nicer interface to extension objects (CXX_Extensions)
Example:
extern "C" void initexample();
static ExtensionModule* example;
void initexample()
{
example = new ExtensionModule("example");
example->add("sum", ex_sum,
"sum(arglist) = sum of arguments");
example->add("test", ex_test,
"test(arglist) runs a test suite");
Dict d = example->initialize();
d["a_constant"] = b.getAttr("c");
}

Page 45
An Overview of the Numeric Extensions to Python - 7th Python Workshop - Houston TX - November 10, 1998 Numeric Python Tutorial - © 1998, David Ascher
89
CXX Example
static string test_Dict() {
// test the Dict class
Dict a,b;
List v;
String s("two");
a["one"] = Int(1);
a[s] = Int(2);
a["three"] = Int(3);
v = a.values();
sort(v.begin(), v.end());
for (int k = 1; k < 4; ++k) {
if (v[k-1] != Int(k))
return "failed 2 " + v.as_string();
}
b = a;
b.clear();
if (b.keys().length() != 0) {
return "failed 3 " + b.as_string();
}
return "ok";
}
90
CXX and NumPy
try{
Array t(12);
for(int i=0; i < t.length(); ++i) {
t[i] = Float(i / 2.0);
}
x = t.rank();
s = t.species();
d1 = t.dimension(1);
List w(3);
w[0] = Float(9.0);
w[1] = Float(4.0);
w[2] = Float(1.0);
Array from_list = toArray(w);
Array sum = from_list + from_list;
sum = from_list + Int(2);
float v = from_list[1];
std::sort(from_list.begin(), from_list.end());
}
catch(Exception&) {
std::cout << "Test failed via Exception" << std::endl;
PyErr_Fetch (&ptype, &pvalue, &ptrace);
FromAPI p(pvalue);
Object v(p);
std::cout << v << std::endl;
}

Page 46
An Overview of the Numeric Extensions to Python - 7th Python Workshop - Houston TX - November 10, 1998 Numeric Python Tutorial - © 1998, David Ascher
91
Support & Documentation
Support:
Bug reports should go to
support@icf.llnl.gov
Documentation
– Currently being written in collaboration with the folks
at LLNL:
• Tutorial
• Reference Manual
– Will announce on comp.lang.python and matrix-sig
when draft ready for feedback.
Web Information:
– Scientific Computation Topic Guide:
http://www.python.org/topics/scicomp/
– NumPy FAQ (to add entries: password is
Descartes
):
http://www.python.org/cgi-bin/numpy-faq
92
JNumeric
Tim Hochberg (
hochberg@psn.net
) has started
JNumeric -- an implementation of NumPy in
Java/JPython.
Very early stages yet, but promising -- very small code
base (--> hopefully few bugs), and because in JPython,
has some nice features (subclassable, rich comparisons
easier to code, etc.).
See
http://www.egroups.com/list/jnumeric
for
discussion and other information.

Page 47
An Overview of the Numeric Extensions to Python - 7th Python Workshop - Houston TX - November 10, 1998 Numeric Python Tutorial - © 1998, David Ascher
93
Other Worthy Causes
Rich Comparisons
Full-product indexing
Plotting
– Hopefully I'll release an alpha of my code soon -- I'll
need constructive criticism of the design, as well as
contributions in code.
Computational Libraries:
– Statistics (all kinds)
– Optimization (all kinds)
– Field-specific
Q: How to organize, validate, distribute contributed
libraries?