📚 The CoCalc Library - books, templates and other resources
License: OTHER
"""This file contains code used in "Think DSP",1by Allen B. Downey, available from greenteapress.com23Copyright 2014 Allen B. Downey4License: GNU GPLv3 http://www.gnu.org/licenses/gpl.html5"""67from __future__ import print_function, division89import math10import numpy1112import thinkdsp13import thinkplot1415PI2 = math.pi * 2161718def synthesize1(amps, freqs, ts):19"""Synthesize a mixture of complex sinusoids with given amps and freqs.2021amps: amplitudes22freqs: frequencies in Hz23ts: times to evaluate the signal2425returns: wave array26"""27components = [thinkdsp.ComplexSinusoid(freq, amp)28for amp, freq in zip(amps, freqs)]29signal = thinkdsp.SumSignal(*components)3031ys = signal.evaluate(ts)32return ys333435def synthesize2(amps, freqs, ts):36"""Synthesize a mixture of cosines with given amps and freqs.3738amps: amplitudes39freqs: frequencies in Hz40ts: times to evaluate the signal4142returns: wave array43"""44i = complex(0, 1)45args = numpy.outer(ts, freqs)46M = numpy.exp(i * PI2 * args)47ys = numpy.dot(M, amps)48return ys495051def analyze1(ys, freqs, ts):52"""Analyze a mixture of cosines and return amplitudes.5354Works for the general case where M is not orthogonal.5556ys: wave array57freqs: frequencies in Hz58ts: times where the signal was evaluated5960returns: vector of amplitudes61"""62args = numpy.outer(ts, freqs)63M = numpy.exp(i * PI2 * args)64amps = numpy.linalg.solve(M, ys)65return amps666768def analyze2(ys, freqs, ts):69"""Analyze a mixture of cosines and return amplitudes.7071Assumes that freqs and ts are chosen so that M is orthogonal.7273ys: wave array74freqs: frequencies in Hz75ts: times where the signal was evaluated7677returns: vector of amplitudes78"""7980def analyze2(ys, freqs, ts):81args = numpy.outer(ts, freqs)82M = numpy.exp(i * PI2 * args)83amps = M.conj().transpose().dot(ys) / N84return amps858687def dft(ys):88i = complex(0, 1)89N = len(ys)90ts = numpy.arange(N) / N91freqs = numpy.arange(N)92args = numpy.outer(ts, freqs)93M = numpy.exp(i * PI2 * args)94amps = M.conj().transpose().dot(ys)95return amps969798def idft(amps):99ys = dft(amps) / N100return ys101102103def make_figures():104"""Makes figures showing complex signals.105"""106amps = numpy.array([0.6, 0.25, 0.1, 0.05])107freqs = [100, 200, 300, 400]108framerate = 11025109110ts = numpy.linspace(0, 1, framerate)111ys = synthesize1(amps, freqs, ts)112print(ys)113114thinkplot.preplot(2)115n = framerate / 25116thinkplot.plot(ts[:n], ys[:n].real, label='real')117thinkplot.plot(ts[:n], ys[:n].imag, label='imag')118thinkplot.save(root='dft1',119xlabel='Time (s)',120ylim=[-1.05, 1.05],121loc='lower right')122123ys = synthesize2(amps, freqs, ts)124125amps2 = amps * numpy.exp(1.5j)126ys2 = synthesize2(amps2, freqs, ts)127128thinkplot.preplot(2)129thinkplot.plot(ts[:n], ys.real[:n], label=r'$\phi_0 = 0$')130thinkplot.plot(ts[:n], ys2.real[:n], label=r'$\phi_0 = 1.5$')131thinkplot.save(root='dft2',132xlabel='Time (s)',133ylim=[-1.05, 1.05],134loc='lower right')135136137framerate = 10000138signal = thinkdsp.SawtoothSignal(freq=500)139wave = signal.make_wave(duration=0.1, framerate=framerate)140hs = dft(wave.ys)141amps = numpy.absolute(hs)142143N = len(hs)144fs = numpy.arange(N) * framerate / N145thinkplot.plot(fs, amps)146thinkplot.save(root='dft3',147xlabel='Frequency (Hz)',148ylabel='Amplitude',149legend=False)150151152153def main():154numpy.set_printoptions(precision=3, suppress=True)155make_figures()156157158if __name__ == '__main__':159main()160161162