3 Shinylive in Quarto example
This is a Shinylive application embedded in a Quarto doc.
#| standalone: true
#| viewerHeight: 2000
# components: [editor, viewer]
#| components: [viewer]
#| layout: vertical
from shiny import *
import numpy as np
import matplotlib.pyplot as plt
fft = np.fft.fft
fmin, fmax = 0, 1
app_ui = ui.page_fluid(
ui.layout_sidebar(
ui.panel_sidebar(
ui.input_slider("freq", "Frequency", 0, 0.5, 0.1, step=0.001),
ui.input_slider("N", "Length", 10, 200, 30, step=1),
),
ui.panel_main(
ui.output_plot("plot_signal"),
#ui.output_plot("plot_DTFT_per"),
ui.output_plot("plot_DTFT_rect"),
ui.output_plot("plot_DFT"),
ui.output_plot("plot_DTFT_DFT")
),
),)
def server(input, output, session):
def prepare():
global f, N, n, x
# Read inputs
f = input.freq()
N = input.N()
# Create the signal
n = np.arange(N)
x = np.cos(2*np.pi*f*n)
@output
@render.plot(alt="Sine wave")
def plot_signal():
prepare()
fig = plt.figure(figsize=(6, 3))
plt.plot(x, '-o')
plt.title('The signal $x(t) = \cos(2 \pi f n)$')
plt.xlabel('Discrete time $n$')
plt.ylabel('Signal $x[n]$')
plt.show()
@output
@render.plot(alt="Sine wave")
def plot_DTFT_per():
prepare()
# Regenerate the signal so that it fits in one period
period = 1000*f
ninf = np.arange(period)
xinf = np.cos(2*np.pi*f*ninf)
# Compute the DTFT
Sinf = fft(xinf)
# Create the frequency axis
freqinf = np.linspace(fmin, fmax, len(Sinf))
# Plot the magnitude of the DTFT
plt.figure(figsize=(6, 3))
plt.title('DTFT of infinitely-long periodic signal')
plt.stem(freqinf, np.abs(Sinf), linefmt='b')
plt.xlabel('Frequency')
plt.ylabel('Magnitude')
plt.show()
@output
@render.plot(alt="Sine wave")
def plot_DTFT_rect():
prepare()
# Compute the DTFT
FFT_points = 10000*n.size
S1 = fft(x, FFT_points)
# Create the frequency axis
freq1 = np.linspace(fmin, fmax, len(S1))
# Plot the magnitude of the DTFT
plt.figure(figsize=(6, 3))
plt.title('DTFT of windowed signal')
plt.plot(freq1, np.abs(S1), 'b')
#plt.stem(freqinf, np.abs(Sinf), 'b')
plt.xlabel('Frequency')
plt.ylabel('Magnitude')
plt.show()
@output
@render.plot(alt="Sine wave")
def plot_DFT():
prepare()
# Compute the DFT
S2 = fft(x)
# Create the frequency axis
freq2 = np.linspace(fmin, fmax, len(S2))
#freq2 = np.fft.fftfreq(x.size)
# Plot the magnitude of the DFT
plt.figure(figsize=(6, 3))
plt.title('Its DFT')
plt.stem(freq2, np.abs(S2), linefmt='ro')
plt.xlabel('Frequency')
plt.ylabel('Magnitude')
plt.show()
@output
@render.plot(alt="Sine wave")
def plot_DTFT_DFT():
prepare()
# Compute the DTFT
FFT_points = 10000*n.size
S1 = fft(x, FFT_points)
freq1 = np.linspace(fmin, fmax, len(S1))
# Compute the DFT
S2 = fft(x)
# Plot the DTFT and DFT overlaid
freq2 = np.linspace(fmin, fmax, len(S2)+1)
plt.figure(figsize=(6, 3))
plt.plot(freq1, np.abs(S1), 'b')
plt.stem(freq2[:-1], np.abs(S2), linefmt='ro')
plt.title('The DFT is just sampled from the DTFT')
plt.xlabel('Frequency')
plt.ylabel('Magnitude')
plt.show()
app = App(app_ui, server)