-
Notifications
You must be signed in to change notification settings - Fork 2.2k
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
Implement a Jupyter cell magic %%manim #895
Comments
I've actually been trying to create a package for that but since there is an open issue I would like to share what I've tried so far. What I've done so far is to create a temporary Here is the code: from IPython.core.display import display, HTML
from IPython import get_ipython
from IPython.core.magic import Magics, magics_class, line_magic, cell_magic, line_cell_magic
from IPython.core.magic import needs_local_scope
from pathlib import Path
from subprocess import Popen, PIPE
from tempfile import NamedTemporaryFile
import IPython.display
import os
import re
def find_path(output_string):
output_string = output_string.decode('utf-8')
output_string = re.sub(' ', '', ''.join(output_string.split('\n')))
if m := re.search('(?<=Filereadyat).+(?=INFO)', output_string):
return m.group(0)
@magics_class
class ManimceMagic(Magics):
@cell_magic
def manimce(self, line, cell):
get_ipython().ex(cell)
manimce_args = line.split()
f = NamedTemporaryFile('r+', suffix='.py', delete=False)
try:
f.write(cell)
f.close()
args = ['manimce', f.name, *manimce_args]
p = Popen(args, stdout=PIPE, stdin=PIPE, stderr=PIPE)
output, err = p.communicate()
path = find_path(output)
display(IPython.display.Code(output.decode('utf-8'), language='python3'))
# display(IPython.display.Code(err.decode('utf-8'), language='python3'))
display(p.returncode)
finally:
os.remove(f.name)
if path:
path = Path(path)
relative_path = path.relative_to(Path.cwd())
if '-i' in manimce_args:
return IPython.display.Image(relative_path, width=854, height=480)
else:
return IPython.display.Video(relative_path, width=854, height=480, html_attributes='controls loop autoplay')
def load_ipython_extension(ipython):
ipython.register_magics(ManimceMagic) I've also tried to change |
Thank you for your report! A while ago, I was working on getting Technically, I wouldn't spawn a subprocess and run manimce there, but rather let Python do the work for us: we don't need to have a file containing the code for an animation. It would be more straightforward to have, given a cell %%manim MyAwesomeScene
from manim import Scene, Square, ShowCreation
class MyAwesomeScene(Scene):
def construct(self):
sq = Square()
self.play(ShowCreation(sq)) simply call The biggest problem with this approch is, I feel, providing a clean interface for setting config parameters. While it is possible to simply set the corresponding options using |
I am really excited about this integration idea! Before going into deep details, I have some conceptional thoughts of what this manim jupyter feature should be used for. I could see two approaches:
To give some examples of my idea:
I would rather go with approach 2 then approach 1. Design idea:As %%manim MyAwesomeScene
from manim import Scene, Square, ShowCreation
class MyAwesomeScene(Scene):
def construct(self):
sq = Square()
self.play(ShowCreation(sq)) is a bit clunky. %%manim -q m
from manim import ManimScene, Scene, Square, ShowCreation
manim = ManimScene(Scene):
sq = Square()
manim.play(ShowCreation(sq)) Furhter notes:I think that |
Personally, I would keep the magic cell interface as close as possible to the command line interface as possible: it would seem weird to me, from a UX perspective, to introduce a completely different way how Manim code should be written and run. The advantage I see for writing the exact same code in Jupyter cells as in a normal python file is precisely that: that Jupyter can be used to experiment and for rapid prototyping, and once you are satisfied you can just copy+paste your code in a python file. I don't really understand what you are doing in your last code block; that seems syntactically broken to me. I'd definitely include and display the videos in the jupyter notebook -- just like the current behavior of the |
Yep, it definitely should stay similar.
Yep, I think so too! That was only a brainstorming idea, to get the indention level a bit more to the right, but the copy+paste possibility is also a good point. |
Happy to see that it was merged! I was going to comment that maybe the I am away from keyboard now but will add a mention of your implementation to help users find what they are looking for. Is there a documentation section with examples of the magic usage that I should point to? Edit: sorry I meant to comment on the issue in my repository but I'm on mobile and didn't notice. Anyways I guess it works here too :) |
That's an interesting idea, thanks for sharing! I do think that something like that makes sense; maybe we'll wait with implementing this until we switch to the new webgl renderer; then we might be able to profit even more of custom html representations. And of course: thank you again for bringing up the idea of including IPython capabilities directly!
We did setup a very simple playground on binder, accessible at https://mybinder.org/v2/gist/behackl/725d956ec80969226b7bf9b4aef40b78/HEAD?filepath=basic%20example%20scenes.ipynb -- eventually, I'd like to provide supplementary notebooks to all of our tutorials. I'm not sure yet about the best way of documenting the magic (ideally such that it combines well with Sphinx), but I didn't investigate too much so far.
It does. 😄 |
Description of proposed feature
The package
jupyter_manim
allows a neat integration of (3b1b) Manim in Jupyter notebooks. At some point, we discussed sending a PR to makejupyter_manim
compatible with the community version -- but actually, as has been pointed out in krassowski/jupyter-manim#26, it would be a much better solution to ship the corresponding functionality as a part of our community edition.How can the new feature be used?
See the README in https://github.com/krassowski/jupyter-manim -- just like that.
The text was updated successfully, but these errors were encountered: