POWER
This page runs a BASIC program that graphs a power spectrum: for each frequency ω, how strongly that frequency is present in a function. The program is rewritten in Python and runs right here in your browser. Edit the code and press Run to redraw the graph; Reset brings back the original program.
It improves on DETECTOR. The function here, \(f(t) = 3\sin(7t - \pi/3)\), has a phase shift, so it doesn’t line up with \(\sin(2\pi\omega t)\) alone. The program therefore measures f against both a sine and a cosine at each frequency:
\[ \text{accumS} = \frac{2}{b-a} \int_a^b f(t)\sin(2\pi\omega t)\, dt, \qquad \text{accumC} = \frac{2}{b-a} \int_a^b f(t)\cos(2\pi\omega t)\, dt, \]
and combines them as power = SQR(accumS ^ 2 + accumC ^ 2). Whatever the phase, this comes out near f’s amplitude, 3, at the matching frequency and near 0 elsewhere. The factor 2 is what makes the peak height equal the amplitude, rather than half of it as in DETECTOR.
The loops work as in DETECTOR: the outer loop moves ω from 0 to 3 in 512 steps, and the inner loop computes both integrals with a 64-piece midpoint sum. After the loops, the last LINE draws a vertical segment in color 6 (brown) at \(\omega = 7/(2\pi) \approx 1.114\), where the peak should be, so you can check that it lines up.
As in SEQUENCE, COLOR 8, 7 draws in dark gray on a light gray background; in the Python that is color(8, 7), and line(..., 6) gives the marker its color. Try changing the phase math.pi / 3 and notice that the peak stays the same height, or add a second term to fnf, such as + 1.5 * math.sin(3 * t), and look for its peak at \(3/(2\pi) \approx 0.477\).
QBasic lets a FUNCTION be written at the end of the program, after the code that uses it. Python needs a function to be defined before it is called, so in the Python the def comes first, and return gives back the value that BASIC sets with fnf = .... SIN, COS, SQR, and ATN become math.sin, math.cos, math.sqrt, and math.atan, and BASIC’s comment mark ' becomes #.
One subtlety in the original: QBasic keeps the variables inside a FUNCTION separate from the ones in the main program unless they are declared SHARED. So inside fnf, pi is a new variable that starts at 0, and the original really computes \(3\sin(7t)\) with no phase shift. The Python uses the real π. Since the power spectrum doesn’t depend on the phase, the graph comes out the same either way.
Notes from the textbook
Add notes here.
1 DEFDBL A-Z
2 SCREEN 9
3 COLOR 8, 7
4 WINDOW (0, -.5)-(3, 4)
5 startomega = 0
6 endomega = 3
7 omegasteps = 2 ^ 9
8 deltaomega = (endomega - startomega) / omegasteps
9 pi = 4 * ATN(1)
10 twopi = 2 * pi
11 a = 0
12 b = 10
13 numberofsteps = 2 ^ 6
14 deltat = (b - a) / numberofsteps
15 omega = startomega
16 oldomega = omega
17 oldpower = 0
18 FOR j = 1 TO omegasteps
19 t = a + deltat / 2
20 accumS = 0
21 accumC = 0
22 power = 0
23 FOR k = 1 TO numberofsteps
24 deltaS = 2 * fnf(t) * SIN(twopi * omega * t) * deltat / (b - a)
25 accumS = accumS + deltaS
26 deltaC = 2 * fnf(t) * COS(twopi * omega * t) * deltat / (b - a)
27 accumC = accumC + deltaC
28 t = t + deltat
29 NEXT k
30 power = SQR(accumS ^ 2 + accumC ^ 2)
31 omega = omega + deltaomega
32 LINE (oldomega, oldpower)-(omega, power)
33 oldomega = omega
34 oldpower = power
35 NEXT j
36 LINE (7 / twopi, 0)-(7 / twopi, 3), 6 'this marks the location of the
37 'peak in the power spectrum
38 FUNCTION fnf (t)
39 fnf = 3 * SIN(7 * t - pi / 3)
40 END FUNCTION
Graph
Each line(...) draws one straight segment, like BASIC's LINE;
an optional third number picks its color. window(...) sets the visible range, like WINDOW,
and color(...) sets the colors, like COLOR.
Hover over the graph to read coordinates.
Python code
Press Run (or Ctrl/⌘ + Enter) to redraw the graph. Press Esc, then Tab, to leave the editor.