POWER

In review

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.

Loading Python. The first run takes a few seconds.

Python code

Press Run (or Ctrl/⌘ + Enter) to redraw the graph. Press Esc, then Tab, to leave the editor.

Loading Python…