Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Export the simulation as a video #885

Open
nivedkrishnans opened this issue Aug 19, 2020 · 10 comments
Open

Export the simulation as a video #885

nivedkrishnans opened this issue Aug 19, 2020 · 10 comments
Labels
feature Release notes label

Comments

@nivedkrishnans
Copy link

nivedkrishnans commented Aug 19, 2020

What's the problem this feature will solve?
A readily obtainable video output of our simulation would make it easier for collaboration between people working on a model as well as for presentations, publications, etc. A normal screen recording will not do well, as the time required for each step may fluctuate during a simulation. NetLogo offers an option to record the simulation region or even the whole interface (with the sliders, graphs, etc).

Describe the solution you'd like
Just a thought: It would be better if we can obtain the exact same thing as the browser visualization as a video. Maybe we can screen capture the active elements of the screen during every step and store it temporarily, and at the end of the simulation, stitch them together (say 25 steps per second) and output it into a predefined location/filename.

EDIT: I came across a few python packages that can 'program' svgs. We can assign some shape for every agent and then put them together at the appropriate coordinates to get a vector image for each step. Maybe also display the parameters of the model, etc.

@rht
Copy link
Contributor

rht commented Sep 15, 2023

Temporary solution is to record the browser screen using e.g. https://chrome.google.com/webstore/detail/screen-recorder/hniebljpgcogalllopnjokppmgbhaden.

But given that we use Solara now, it should be easier to capture the Matplotlib space state as pictures that can be turned to animated GIF.

@vagechirkov
Copy link

Temporary solution is to record the browser screen using e.g. https://chrome.google.com/webstore/detail/screen-recorder/hniebljpgcogalllopnjokppmgbhaden.

But given that we use Solara now, it should be easier to capture the Matplotlib space state as pictures that can be turned to animated GIF.

The second option (to capture the matplotlib space state as images) sounds good to me. Any hints on where to start with this? I'm happy to work on this feature if it might be useful to others.

@rht
Copy link
Contributor

rht commented Sep 15, 2023

A quick hack to test the idea is to add a line after

space_ax.set_axis_off()
to save the plot to a file, which filename is an increasing number. And then combine the pictures into 1 file via imagemagick CLI.

@rht
Copy link
Contributor

rht commented Sep 15, 2023

https://askubuntu.com/questions/648244/how-do-i-create-an-animated-gif-from-still-images-preferably-with-the-command-l

@Corvince
Copy link
Contributor

You can also have a look at https://matplotlib.org/stable/api/animation_api.html

Especially the examples on the bottom are helpful to create an animation. No need to use solara here, you can also just do your plots normally and call model.step() inside the Animation function.

@rht
Copy link
Contributor

rht commented Sep 15, 2023

That animation API uses set_data (which is more performant than Solara current update method, which recreates the plot object from scratch every time), which Solara doesn't use. It means there needs to be a separate plot object that is updated using this method after a model step. Not ideal, but if it works, it's fine I suppose.

@vagechirkov
Copy link

A quick hack to test the idea is to add a line after

space_ax.set_axis_off()

to save the plot to a file, which filename is an increasing number. And then combine the pictures into 1 file via imagemagick CLI.

This works well 🎉 I think it might be the easiest integration with the existing infrastructure.

space_ax.set_axis_off()
space_fig.savefig(f"space_{model.schedule.steps}.png")

However, I personally prefer to have a separate function to generate gif for a given model. I guess Matplotlib's animation API is the best option then.

@vagechirkov
Copy link

Here is the implementation using matplotlib.animation:

Show code
import matplotlib.animation as animation
from matplotlib.figure import Figure
from mesa.experimental.jupyter_viz import JupyterContainer


def plot_n_steps(viz_container: JupyterContainer, n_steps: int = 10):
    model = viz_container.model_class(**viz_container.model_params_input, **viz_container.model_params_fixed)

    space_fig = Figure(figsize=(10, 10))
    space_ax = space_fig.subplots()
    space_ax.set_axis_off()
    # set limits to grid size
    space_ax.set_xlim(0, model.grid.width)
    space_ax.set_ylim(0, model.grid.height)
    # set equal aspect ratio
    space_ax.set_aspect('equal', adjustable='box')

    scatter = space_ax.scatter(**viz_container.portray(model.grid))

    def update_grid(_scatter, data):
        _scatter.set_offsets(list(zip(data["x"], data["y"])))
        if "c" in data:
            _scatter.set_color(data["c"])
        if "s" in data:
            _scatter.set_sizes(data["s"])
        return _scatter

    def animate(_):
        if model.running:
            model.step()
        return update_grid(scatter, viz_container.portray(model.grid))

    ani = animation.FuncAnimation(space_fig, animate, repeat=True, frames=n_steps, interval=400)

    # To save the animation using Pillow as a gif
    writer = animation.PillowWriter(fps=15, metadata=dict(artist='Me'), bitrate=1800)
    ani.save('scatter.gif', writer=writer)

It's actually pretty fast: ~10 seconds for 1000 steps and 5 agents. Please let me know what you think @rht @Corvince!

@rht
Copy link
Contributor

rht commented Sep 18, 2023

We could incorporate your code, but there is a possibility that we are migrating the plotting to Altair instead (see #1806). This is still up for discussion.

@vagechirkov
Copy link

We could incorporate your code, but there is a possibility that we are migrating the plotting to Altair instead (see #1806). This is still up for discussion.

Just let me know if this or something like it might be useful, I am actively using this to produce gifs to check the model when running on the compute cluster.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature Release notes label
Projects
None yet
Development

No branches or pull requests

5 participants