What does the matplotlib "Embedding in TK" example actually do?

Hello all,

I’m looking at embedding a matplotlib figure in a Tkinter program, but looking at the example given in the matplotlib user guide I can’t work out what it’s actually meant to graph (I appreciate some would consider this more of a raw maths question than a Python one). Specifically I can’t work out what the call to ax.plot() on the 16th line is supposed to be plotting.

I can see that t is a numpy.ndarray object containing values ranging from 0 to 2.9 inclusive in increments of 0.1, so it contains 30 discrete values. I’ve worked out that multiplying a np.array object by x will multiply each member of the array by x (as opposed to duplicating the array x times as would be the case with a standard python list). Given the presence of np.sine() and 2* pi I’ve a feeling it relates to radians and trigonometry but I can’t work out what it’s supposed to graph.

Of course the x axis is labeled time [s] and the y axis is f(t) which, considering the handler update_frequency() might be frequency(time).

At first I thought it was meant to graph the sine value of angles encompassing 1/10th of a circle, 2/10th’s of a circle, etc. But the values in t exceed 1 so that doesn’t make sense - plus the value returned by np.sine() is multiplied by 2, and none of that relates to frequency or time in any obvious way. I wish the author had just included a comment explaining what the code is supposed to plot :frowning_with_open_mouth:

If someone could point me in the right direction I’d be super grateful! I’ve posted the example from the matplotlib user guide below.

import tkinter

import numpy as np

# Implement the default Matplotlib key bindings.
from matplotlib.backend_bases import key_press_handler
from matplotlib.backends.backend_tkagg import (FigureCanvasTkAgg,
                                               NavigationToolbar2Tk)
from matplotlib.figure import Figure

root = tkinter.Tk()
root.wm_title("Embedding in Tk")

fig = Figure(figsize=(5, 4), dpi=100)
t = np.arange(0, 3, .01)
ax = fig.add_subplot()
line, = ax.plot(t, 2 * np.sin(2 * np.pi * t))
ax.set_xlabel("time [s]")
ax.set_ylabel("f(t)")

canvas = FigureCanvasTkAgg(fig, master=root)  # A tk.DrawingArea.
canvas.draw()

# pack_toolbar=False will make it easier to use a layout manager later on.
toolbar = NavigationToolbar2Tk(canvas, root, pack_toolbar=False)
toolbar.update()

canvas.mpl_connect(
    "key_press_event", lambda event: print(f"you pressed {event.key}"))
canvas.mpl_connect("key_press_event", key_press_handler)

button_quit = tkinter.Button(master=root, text="Quit", command=root.destroy)


def update_frequency(new_val):
    # retrieve frequency
    f = float(new_val)

    # update data
    y = 2 * np.sin(2 * np.pi * f * t)
    line.set_data(t, y)

    # required to update canvas and attached toolbar!
    canvas.draw()


slider_update = tkinter.Scale(root, from_=1, to=5, orient=tkinter.HORIZONTAL,
                              command=update_frequency, label="Frequency [Hz]")

# Packing order is important. Widgets are processed sequentially and if there
# is no space left, because the window is too small, they are not displayed.
# The canvas is rather flexible in its size, so we pack it last which makes
# sure the UI controls are displayed as long as possible.
button_quit.pack(side=tkinter.BOTTOM)
slider_update.pack(side=tkinter.BOTTOM)
toolbar.pack(side=tkinter.BOTTOM, fill=tkinter.X)
canvas.get_tk_widget().pack(side=tkinter.TOP, fill=tkinter.BOTH, expand=True)

tkinter.mainloop()

f(t) is just some arbitrary function, the actual values are not the point of the example. It plots some function in time from t=0 to t=3 in dt=0.01 steps (not 0.1). Specifically, this function is a sine function with a configurable frequency, see a documentation for trig functions like this one: Amplitude, Period, Phase Shift and Frequency

1 Like

Thanks, I’ve got to admit that I was completely baffled when I first checked out your link, and couldn’t immediately see how it related to the sine I knew from basic trigonometry on right angled triangles. But I think I’ve got it sussed now.

So on the plot, the x axis is time and it ranges from 0 to 2.99 units of whatever the unit measurement is (I’ll assume seconds as the example doesn’t elaborate). The y axis records values of the sine function to which a multiplier has been applied to account for amplitude (which in this case is 2).

Assuming no frequency has been configured it effectively defaults to 1, so each unit of time on the x axis accounts for one ‘period’. If a frequency is configured the plotted line is rearranged.

There is this relationship between the frequency and the computed sine value that I’ll try to put into words: a frequency of two means two complete oscillations occur in one unit of time, thus the period is halved and the angles on which the sine is computed (and by extension the sine values themselves) advance at 2x the rate, e.g:

# frequency == 2
# for each value in t, radians_b is 2x radians_a
radians_a = 2 * np.pi * t
radians_b = 2 * np.pi * 2 * t
# when plotted as a function of t, b rises and falls 2x faster than a
a = 2 * np.sine(radians_a)
b = 2 * np.sine(radians_b)

I’m sure someone else can characterize it much more succinctly than I have there.

Hi,

your query header:

What does the matplotlib ‘Embedding in TK’ example actually do?

The purpose of the example is to embed tkinter functionality to the graph. Generally when you plot some function, the graph is static. That is, it is kind of a snap shot of a function over some given values. By embedding tkinter into the graph in this example, they are making it dynamic via the following widgets (since they are not provided automatically by matplotlib graphing package):

embedding_part

By embedding tkinter widgets to the graph, the user can manipulate the graph in real time by varying the frequency in this particular example. It even provides a Quit button to close the graph.

Hope this helps.