Get help from the marimo community

Updated 6 days ago

How to avoid flickering display when using sliders to update a matplotlib graph?

At a glance

The community member created a "notebook" using mo.ui.slider to trigger the redraw of a Matplotlib plot, but found the approach to be naive and the result to be ugly. They tried an in-place update routine before using Marimo, but it required the figure to be set up beforehand, which they didn't know how to do. The community member was unsure how to smartly update the plot in Marimo without triggering a full draw again, which caused the plot to flicker.

In the comments, the community member found a link to the Marimo documentation for working with Plotly and Altair, and tried using those libraries, but didn't have any more success in associating a slider with a modification of the content passed to Altair.

<answer>The community member found the solution in the Marimo tutorials, and it involved using the <code>@mo.cache</code> decorator and <code>plt.gca()</code>. The updated code is provided in the answer.</answer>
Useful resources

I made a "notebook" where I use a mo.ui.slider which triggers the redraw of a matplotlib plot. But my approach is very naive and the result is ugly:

Python
# first
phi = mo.ui.slider(-10, 10, 0.1, value=-2, label="$\\varphi$")

# then
plt.plot(x_arr, np.sin(x_arr + phi.value))
plt.show()

Before marimo, I used some kind of in-place update routine like :

Python
line.set_ydata(np.sin(x_arr + phi.value))
fig.canvas.draw()

But it requires the figure to be setup beforehand... And I don't know how to do that

I don't know how to smartly update the plot in marimo, without triggering a full draw again. Full draw which causes the plot to flicker, which looks ugly...

Here is the snippet of code I'm talking about if you wanna see by yourself

Python
import marimo

__generated_with = "0.10.13"
app = marimo.App()


@app.cell(hide_code=True)
def _():
    import marimo as mo
    import numpy as np

    import matplotlib.pyplot as plt
    return mo, np, plt


@app.cell
def _(mo, np):
    x_arr = np.linspace(-8, 8, 1024)

    phi = mo.ui.slider(-10, 10, 0.1, value=-2, label="$\\varphi$")
    return phi, x_arr


@app.cell
def _(mo, phi):

    mo.vstack([
        mo.hstack([phi, mo.md(f"{phi.value:0.02f}"),]),
    ])
    return


@app.cell
def _(np, phi, plt, x_arr):
    plt.plot(x_arr, np.sin(x_arr + phi.value))
    plt.grid()
    plt.show()
    return


if __name__ == "__main__":
    app.run()






Marked as solution

I found the solution, it was in the tutorials :D

I guess the trick lies in the @mo.cache, or the plt.gca() ... I dunno


Python
import marimo

__generated_with = "0.11.17"
app = marimo.App()


@app.cell(hide_code=True)
def _():
	import marimo as mo
	import numpy as np

	import matplotlib.pyplot as plt
	return mo, np, plt


@app.cell
def _(mo, np):
	x_arr = np.linspace(-8, 8, 1024)

	phi = mo.ui.slider(-10, 10, 0.1, value=-2, label="$\\varphi$")
	return phi, x_arr


@app.cell
def _(mo, np, plt, x_arr):
	@mo.cache
	def plot_it(phi):
		plt.plot(x_arr, np.sin(x_arr + phi.value))
		plt.grid()
		return plt.gca()
	return (plot_it,)


@app.cell
def _(mo, phi):
	mo.vstack([
		mo.hstack([phi, mo.md(f"{phi.value:0.02f}"),]),
	])
	return


@app.cell
def _(phi, plot_it):
	plot_it(phi)
	return


if __name__ == "__main__":
	app.run()


View full solution
y
2 comments·1 reply
This comment has been deleted.
This comment has been deleted.

I found the solution, it was in the tutorials :D

I guess the trick lies in the @mo.cache, or the plt.gca() ... I dunno


Python
import marimo

__generated_with = "0.11.17"
app = marimo.App()


@app.cell(hide_code=True)
def _():
	import marimo as mo
	import numpy as np

	import matplotlib.pyplot as plt
	return mo, np, plt


@app.cell
def _(mo, np):
	x_arr = np.linspace(-8, 8, 1024)

	phi = mo.ui.slider(-10, 10, 0.1, value=-2, label="$\\varphi$")
	return phi, x_arr


@app.cell
def _(mo, np, plt, x_arr):
	@mo.cache
	def plot_it(phi):
		plt.plot(x_arr, np.sin(x_arr + phi.value))
		plt.grid()
		return plt.gca()
	return (plot_it,)


@app.cell
def _(mo, phi):
	mo.vstack([
		mo.hstack([phi, mo.md(f"{phi.value:0.02f}"),]),
	])
	return


@app.cell
def _(phi, plot_it):
	plot_it(phi)
	return


if __name__ == "__main__":
	app.run()