5 Best Ways to Use Bokeh to Generate Sinusoidal Waves in Python

πŸ’‘ Problem Formulation: Generating visual representations of sinusoidal waves can be challenging, especially when seeking to create interactive visualizations. In this article, we explore various methods using Bokeh, a powerful Python library for interactive visualization, to generate and plot sinusoidal waves. We’ll start with basic implementations and move to more advanced techniques, with the input being parameters such as amplitude, frequency, and phase, and the desired output being an interactive sinusoidal wave plot.

Method 1: Basic Sinusoidal Wave

Bokeh’s plotting interface can be used to create simple sinusoidal waves by plotting sin functions over a range of x values. This method involves setting up a figure and using the line glyph to create a wave pattern.

Here’s an example:

from bokeh.plotting import figure, show, output_file
from math import pi, sin
import numpy as np

# Configure the output to display in a separate HTML file
output_file("sinusoidal.html")

# Create a range of x values
x = np.arange(0, 4 * pi, 0.1)
y = [sin(i) for i in x]

# Create a new figure
p = figure(title="Basic Sinusoidal Wave")

# Add a line plot for the sine wave
p.line(x, y, legend_label="y=sin(x)")

# Show the results
show(p)

The output is an interactive sine wave displayed in a new tab or window as a separate HTML file.

This code snippet generates a basic sinusoidal wave. The x-axis values are taken from 0 to \(4\pi\) with increments of 0.1, which are then applied to a sine function to get corresponding y-axis values. These are plotted on the figure ‘p’, creating a simple interactive plot of a sine wave.

Method 2: Multiple Sinusoidal Waves

Using Bokeh, multiple sinusoidal waves with different frequencies and amplitudes can be layered on top of each other for comparison or for creating complex waveforms.

Here’s an example:

from bokeh.plotting import figure, show, output_file
from math import pi, sin

# Configure the output to display in a separate HTML file
output_file("multiple_sinusoids.html")

# Create a range of x values
x = np.arange(0, 4 * pi, 0.1)

# Define the parameters for 3 different sine waves
params = [
    (1, 1, 0),    # amplitude, frequency, phase
    (0.5, 2, pi / 4),
    (1.5, 0.5, pi / 2)
]

# Create a new figure
p = figure(title="Multiple Sinusoidal Waves")

# Generate and add each sine wave to the plot
for amplitude, frequency, phase in params:
    y = [amplitude * sin(frequency * xi + phase) for xi in x]
    p.line(x, y, legend_label=f"Amp: {amplitude}, Freq: {frequency}, Phase: {phase}")

# Show the results
show(p)

The output is an interactive plot with multiple overlapping sinusoidal waves of different properties.

The code first specifies a few sets of sine wave parameters for amplitude, frequency, and phase. It then generates y-axis values for each set and creates a line on the same plot. As a result, multiple sine waves are combined in one figure, allowing for easy comparison or additive synthesis.

Method 3: Animated Sinusoidal Wave

Bokeh can produce dynamic visuals by animating a sinusoidal wave using its server functionalities. This can be useful for observing wave properties in real-time.

Here’s an example:

from bokeh.plotting import figure, show, output_file, curdoc
from bokeh.models import ColumnDataSource
from math import pi, sin
from bokeh.driving import linear

# Create a blank figure
p = figure(title="Animated Sinusoidal Wave")

# Set up the data source with initial values
source = ColumnDataSource(data=dict(x=[], y=[]))

# Add a line plot with the data source
p.line(x='x', y='y', source=source)

# Automatic update function for the sine wave
@linear()
def update(step):
    x = step / 50.0 * pi
    y = sin(x)
    new_data = dict(x=[x], y=[y])
    source.stream(new_data, rollover=200)

# Add the update function to the curdoc
curdoc().add_root(p)
curdoc().add_periodic_callback(update, 50)

The dynamic output will display a continuously updating sinusoidal wave in the browser.

This code snippet shows how to create an animated sinusoid wave using Bokeh’s server capabilities. An update function is defined, which modifies the data source’s content and causes the plot to render continuously updated frames. By streaming new data points and setting a rollover limit, the wave appears to be moving.

Method 4: Interactive Parameters

Bokeh’s widgets can be layered with interactive plots, allowing users to alter parameters like frequency, amplitude, and phase on-the-fly, to dynamically modify the sinusoidal wave.

Here’s an example:

from bokeh.plotting import figure, show, output_file
from bokeh.layouts import column
from bokeh.models import Slider, ColumnDataSource
from bokeh.io import curdoc
import numpy as np

# Set up data source with initial wave
x = np.linspace(0, 4 * pi, 200)
y = np.sin(x)
source = ColumnDataSource(data=dict(x=x, y=y))

# Set up plot
plot = figure(height=400, width=400, title="Interactive Sinusoidal Wave")
plot.line('x', 'y', source=source)

# Set up widgets
freq_slider = Slider(start=0.1, end=5, value=1, step=.1, title="Frequency")
amp_slider = Slider(start=0.1, end=2, value=1, step=.1, title="Amplitude")
phase_slider = Slider(start=0, end=2*pi, value=0, step=.1, title="Phase")

# Callbacks
def update_wave(attrname, old, new):
    freq = freq_slider.value
    amp = amp_slider.value
    phase = phase_slider.value
    y = amp * np.sin(freq * x + phase)
    source.data = dict(x=x, y=y)

for w in [freq_slider, amp_slider, phase_slider]:
    w.on_change('value', update_wave)

# Arrange plots and widgets in a layout
curdoc().add_root(column(freq_slider, amp_slider, phase_slider, plot))
curdoc().title = "Sinewaves"

The output is an interactive sine wave plot with sliders that allow for real-time adjustments of its properties.

This example extends the Bokeh application by including interactive widgets (sliders) that let the user manipulate the frequency, amplitude, and phase of the plotted sinusoid wave. The update_wave function, attached to the sliders’ on_change event, recalculates the y-axis data anytime a slider’s value is changed.

Bonus One-Liner Method 5: Static Sinusoidal Wave Generator

For a quick and concise generation of a static sinusoidal wave, this one-liner method provides a simple way to create a plot without the need for excessive code overhead or customization.

Here’s an example:

show(figure(title="Static Sinusoidal Wave").line(x=np.linspace(0, 4*pi, 200), y=np.sin(np.linspace(0, 4*pi, 200))))

The output is a simple static sinusoidal wave plot.

This one-liner leverages Bokeh’s streamline capabilities to generate a static sinusoid wave with default settings, minimizing the boilerplate code while still providing a basic interactive graphing utility.

Summary/Discussion

  • Method 1: Basic Sinusoidal Wave. Simple and quick to implement. Limited customization and feature set.
  • Method 2: Multiple Sinusoidal Waves. Enables visualization of multiple waves; suited for comparison. Slightly more complex implementation.
  • Method 3: Animated Sinusoidal Wave. Rich, real-time visuals; great for dynamic demonstrations. Requires running a Bokeh server and more sophisticated setup.
  • Method 4: Interactive Parameters. Highly interactive and educational. Complexity is higher due to callbacks and widget management.
  • Bonus Method 5: Static Sinusoidal Wave Generator. Extremely easy to use and useful for quick plots. Not suitable for complex or interactive visualizations.