I’m a member of
the BuenaSeñal
group. It is a Spanish speaking group where we talk about signal processing
techniques, and audio applications. I’m trying to convince the folks there that
Squeak is a great tool for signal processing.
Hernán Ordiales
said he was looking for alternatives to Matlab, and heard about Python (if you
can read Spanish, he describes his first experience with Python here).
Squeak is an open and free implementation of
Smalltalk. It’s my choice whenever I can use it.
As a short
exercise to learn a bit about Python, Hernán did plots of magnitude and phase
of the FFT of an array consisting of ten 1’s and ninety 0’s. His Python code is
below.
So, I thought he
would enjoy a Squeak version (Hernán, I hope you do!). My Squeak code after
his. Please note that this is neither a tutorial nor a real introduction to
Smalltalk. It is just a small code example, to take a look if you have ten minutes.
#!/usr/bin/python
# -*- coding:
UTF-8 -*-
from pylab
import *
L = 10
x = ones( L )
# Figura 3: N = 100
N = 100
X = fft( x, N )
figure(3)
subplot(311)
title('N =
100')
horiz =
arange(0,L,1)
stem( horiz, x
)
subplot(312)
horiz =
arange(0,N,1)
stem( horiz,
abs(X) )
subplot(313)
stem( horiz,
angle(X) )
savefig(
'figura3.png' )
show()
Display
fillGray.
pi := Float pi.
fft := FFT new:
128.
fft realData
atAll: (1 to: 10) put: 1.
fft
transformForward: true.
abs := fft
realData with: fft imagData collect: [ :r :i | (r@i) r].
fft plot: abs
in: (20@20 extent: 880@320).
angle := fft
realData with: fft imagData collect: [ :r :i | (r@i) theta].
angle := angle
collect: [ :a | a negated + pi \\ (2 * pi ) - pi].
fft plot: angle
in: (20@380 extent: 880@320).
Display
writeBMPfileNamed: 'image4.bmp'.
Below you can
see the generated plot.
The code is
short enough to comment each line. The first thing to know is that in Smalltalk
all the programming is done by sending messages to objects. The syntax is a bit
different from most languages, but it is easy to read.
The line Display fillGray. erases the display.
The line pi := Float pi. assigns to variable pi the result of
sending message #pi to object Float. Therefore variable pi contains the
floating point number for Pi. Asignment is done with := . We usually prefix the
name of messages with #.
The line fft := FFT new: 128. assigns a new FFT object of size 128 to variable
fft. FFT and Float are existing objects. They are classes (like classes in any
object oriented language). In Smalltalk, classes are regular objects and you
can send them messages, like #pi or #new:. In Squeak, FFT is implemented for
sizes being integer powers of two.
The line fft realData atAll: (1 to: 10) put: 1. puts the value 1 at the first ten positions
of the real input to the FFT. This is done by first asking the fft for its
realData, and sending to the array the message #atAll:put:. The arguments to
this call are the interval [1..10] and 1.
The line fft transformForward: true. does the transform, in “forward” direction,
i.e. from time domain to frequency domain.
The line abs := fft realData with: fft imagData
collect: [ :r :i | (r@i) r]. assigns to variable abs the magnitudes of the result.
The line fft plot: abs in: (20@20 extent: 880@320). plots variable abs.
The line angle := fft realData with: fft imagData
collect: [ :r :i | (r@i) theta]. assigns to variable angle the angles of the result.
The line angle := angle collect: [ :a | a negated +
pi \\ (2 * pi ) - pi]. adjust for a difference between Squeak and Python, to get the same
graph as Hernán. In Python the angles for complex numbers are in [-pi .. pi]
and in Squeak in [0 .. 2pi].
The line fft plot: angle in: (20@380 extent: 880@320). plots variable angle.
The line Display writeBMPfileNamed: 'image4.bmp' saves the graphs in a file.
In the first
version, we had to obtain the magnitudes and phase angles of the results “by
hand”. But in Smalltalk it is very easy to add new methods to any class. Next
time we want to do something alike, we won’t have to write all over again. So,
let’s add these 5 methods to class FFT:
magnitudes
^realData with: imagData collect: [ :r
:i | (r@i) r]
angles
^realData with: imagData collect: [ :r
:i | (r@i) theta]
angles2
| pi |
pi := Float pi.
^self angles collect: [ :a | a negated
+ pi \\ (2 * pi ) - pi]
plotMagnitudesIn:
aRectangle
self plot: self magnitudes in:
aRectangle
plotAnglesIn:
aRectangle
self plot: self angles2 in: aRectangle
The first line
of a method is it’s name (the message) and is aligned to the left. The rest of
the code is indented to the right. | pi | is the way to declare a local
variable. ^ is the way to return an object as a result of the message send. I
hope the purpose of the methods is obvious, as they repeat code from the first
version. Now the script is:
Display
fillGray.
fft := FFT new:
128.
fft realData
atAll: (1 to: 10) put: 1.
fft
transformForward: true.
fft
plotMagnitudesIn: (20@20 extent: 880@320).
fft plotAnglesIn: (20@380 extent: 880@320).
Display
writeBMPfileNamed: 'image4.bmp'
A bit shorter,
isn’t it? This is the generated graph:
BuenaSeñal
folks, I hope you liked this tiny example of Squeak.
Juan Vuletich