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

Crash when using plot_implicit_curve on Axes with certain range #4090

Closed
henrikmidtiby opened this issue Jan 3, 2025 · 5 comments · Fixed by #4091
Closed

Crash when using plot_implicit_curve on Axes with certain range #4090

henrikmidtiby opened this issue Jan 3, 2025 · 5 comments · Fixed by #4091

Comments

@henrikmidtiby
Copy link
Contributor

Description of bug / unexpected behavior

When plotting a certain function using plot_implicit_curve on an axes object with a certain range, manim crashes.

Expected behavior

I would expect that manim did not crash.

How to reproduce the issue

To reproduce the issue do the following

  1. Check out commit 17d4a7f of manim
  2. Create a file named implicit_plot_issue.py with the content given below
  3. Optional - Insert a new line in vectorized_mobject.py after line 1060 with the content print(f"points.shape: { points.shape }") this is to help with debugging
  4. Run manim on the file
  5. The traceback from the error is now shown.
Code for reproducing the problem

Content of implicit_plot_issue.py

from __future__ import annotations

from manim import *


class ImplicitCurveIssue(Scene):
    def construct(self):
        ax = Axes(
            x_range=[0, 10, 2],
            y_range=[0, 10, 2],
        )

        line = ax.plot_implicit_curve(
            lambda x, y: x * 1.7 + y - 4,
        )

        self.add(ax)
        self.add(line)

        return


with tempconfig({"quality": "medium_quality", "disable_caching": True}):
    scene = ImplicitCurveIssue()
    scene.render()

Additional media files

No media files are generated.

Logs

Terminal output
$ manim -v DEBUG PerformanceTests/implicit_plot_issue.py 
Manim Community v0.18.1

points.shape: (3, 3)
points.shape: (3, 3)
points.shape: (258, 3)
points.shape: (0, 3)
Traceback (most recent call last):
  File "/home/hemi/.cache/pypoetry/virtualenvs/manim-RUJt0FvT-py3.10/bin/manim", line 6, in <module>
    sys.exit(main())
  File "/home/hemi/.cache/pypoetry/virtualenvs/manim-RUJt0FvT-py3.10/lib/python3.10/site-packages/click/core.py", line 1157, in __call__
    return self.main(*args, **kwargs)
  File "/home/hemi/.cache/pypoetry/virtualenvs/manim-RUJt0FvT-py3.10/lib/python3.10/site-packages/click/core.py", line 1078, in main
    rv = self.invoke(ctx)
  File "/home/hemi/.cache/pypoetry/virtualenvs/manim-RUJt0FvT-py3.10/lib/python3.10/site-packages/click/core.py", line 1688, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/home/hemi/.cache/pypoetry/virtualenvs/manim-RUJt0FvT-py3.10/lib/python3.10/site-packages/click/core.py", line 1434, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/home/hemi/.cache/pypoetry/virtualenvs/manim-RUJt0FvT-py3.10/lib/python3.10/site-packages/click/core.py", line 783, in invoke
    return __callback(*args, **kwargs)
  File "/home/hemi/localbuild/manim/manim/cli/render/commands.py", line 121, in render
    for SceneClass in scene_classes_from_file(file):
  File "/home/hemi/localbuild/manim/manim/utils/module_ops.py", line 167, in scene_classes_from_file
    module = get_module(file_path)
  File "/home/hemi/localbuild/manim/manim/utils/module_ops.py", line 67, in get_module
    spec.loader.exec_module(module)
  File "<frozen importlib._bootstrap_external>", line 883, in exec_module
  File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
  File "/home/hemi/localbuild/manim/PerformanceTests/implicit_plot_issue.py", line 25, in <module>
    scene.render()
  File "/home/hemi/localbuild/manim/manim/scene/scene.py", line 237, in render
    self.construct()
  File "/home/hemi/localbuild/manim/PerformanceTests/implicit_plot_issue.py", line 13, in construct
    line = ax.plot_implicit_curve(
  File "/home/hemi/localbuild/manim/manim/mobject/graphing/coordinate_systems.py", line 819, in plot_implicit_curve
    graph = ImplicitFunction(
  File "/home/hemi/localbuild/manim/manim/mobject/graphing/functions.py", line 296, in __init__
    super().__init__(**kwargs)
  File "/home/hemi/localbuild/manim/manim/mobject/types/vectorized_mobject.py", line 171, in __init__
    super().__init__(**kwargs)
  File "/home/hemi/localbuild/manim/manim/mobject/mobject.py", line 118, in __init__
    self.generate_points()
  File "/home/hemi/localbuild/manim/manim/mobject/graphing/functions.py", line 315, in generate_points
    self.add_points_as_corners(curve[1:])
  File "/home/hemi/localbuild/manim/manim/mobject/types/vectorized_mobject.py", line 1066, in add_points_as_corners
    start_corners[0] = self.points[-1]
IndexError: index 0 is out of bounds for axis 0 with size 0

System specifications

System Details
  • OS (with version, e.g., Windows 10 v2004 or macOS 10.15 (Catalina)):
  • RAM:
  • Python version (python/py/python3 --version):
  • Installed modules (provide output from pip list):
Ubuntu 22.04
32 GB ram


(manim-py3.10) hemi@sdu-134679:~/localbuild/manim$ python --version
Python 3.10.12
(manim-py3.10) hemi@sdu-134679:~/localbuild/manim$ pip list
Package                       Version         Editable project location
----------------------------- --------------- ---------------------------
alabaster                     0.7.16
av                            12.3.0
babel                         2.16.0
beautifulsoup4                4.12.3
certifi                       2024.8.30
cffi                          1.17.0
cfgv                          3.4.0
charset-normalizer            3.3.2
click                         8.1.7
cloup                         3.0.5
contourpy                     1.3.0
coverage                      7.6.1
cryptography                  43.0.1
cycler                        0.12.1
decorator                     5.1.1
Deprecated                    1.2.14
distlib                       0.3.8
docutils                      0.20.1
exceptiongroup                1.2.2
execnet                       2.1.1
filelock                      3.15.4
fonttools                     4.53.1
furo                          2023.9.10
gitdb                         4.0.11
GitPython                     3.1.43
glcontext                     3.0.0
identify                      2.6.0
idna                          3.8
imagesize                     1.4.1
iniconfig                     2.0.0
isort                         5.13.2
isosurfaces                   0.1.2
Jinja2                        3.1.4
kiwisolver                    1.4.5
manim                         0.18.1          /home/hemi/localbuild/manim
ManimPango                    0.5.0
mapbox_earcut                 1.0.2
markdown-it-py                3.0.0
MarkupSafe                    2.1.5
matplotlib                    3.9.2
mdit-py-plugins               0.4.1
mdurl                         0.1.2
moderngl                      5.11.1
moderngl-window               2.4.6
multipledispatch              1.0.0
myst-parser                   2.0.0
networkx                      3.2.1
nodeenv                       1.9.1
numpy                         1.26.4
packaging                     24.1
pillow                        10.4.0
pip                           24.2
platformdirs                  4.2.2
pluggy                        1.5.0
pre-commit                    3.8.0
psutil                        5.9.8
psutil-wheels                 5.8.0
py                            1.11.0
pycairo                       1.26.1
pycparser                     2.22
pydub                         0.25.1
PyGithub                      2.4.0
pyglet                        2.0.17
Pygments                      2.18.0
PyJWT                         2.9.0
PyNaCl                        1.5.0
pyparsing                     3.1.4
pyrr                          0.10.3
pytest                        7.4.4
pytest-cov                    4.1.0
pytest-forked                 1.6.0
pytest-xdist                  2.5.0
python-dateutil               2.9.0.post0
PyYAML                        6.0.2
requests                      2.32.3
rich                          13.8.0
ruff                          0.6.3
scipy                         1.13.1
screeninfo                    0.8.1
six                           1.16.0
skia-pathops                  0.8.0.post1
smmap                         5.0.1
snakeviz                      2.2.2
snowballstemmer               2.2.0
soupsieve                     2.6
Sphinx                        7.4.7
sphinx-basic-ng               1.0.0b2
sphinx-copybutton             0.5.2
sphinxcontrib-applehelp       2.0.0
sphinxcontrib-devhelp         2.0.0
sphinxcontrib-htmlhelp        2.1.0
sphinxcontrib-jsmath          1.0.1
sphinxcontrib-programoutput   0.17
sphinxcontrib-qthelp          2.0.0
sphinxcontrib-serializinghtml 2.0.0
sphinxext-opengraph           0.9.1
srt                           3.5.3
svgelements                   1.9.6
tomli                         2.0.1
tornado                       6.4.2
tqdm                          4.66.5
types-decorator               0.1.7
types-docutils                0.21.0.20240724
types-Pillow                  10.2.0.20240822
types-Pygments                2.18.0.20240506
types-setuptools              74.0.0.20240830
typing_extensions             4.12.2
urllib3                       2.2.2
virtualenv                    20.26.3
watchdog                      5.0.0
wrapt                         1.16.0

Additional comments

It seems like the method add_points_as_corners is called with an empty list of points, which it cannot handle and thus crashes.

If the x or y range of the Axes are changed the issue disapear in most cases.
The issue can also vanish if the function to plot is changed.

@uwezi
Copy link
Contributor

uwezi commented Jan 4, 2025

Do you mean that you are running a modified Manim with your commit?
Because in an unmodified Manim 0.18.1 your example code does not crash...

image

@chopan050
Copy link
Contributor

chopan050 commented Jan 4, 2025

Do you mean that you are running a modified Manim with your commit?
Because in an unmodified Manim 0.18.1 your example code does not crash...

Actually, it corresponds to the current state of the main branch of Manim. That last commit comes from PR #3999 which Henrik (the OP) created and I reviewed and merged 2 days ago, although it's likely that a previous commit caused the bug, since this PR was about typehinting the utils module. I'll take a look and see what I can find.

@chopan050
Copy link
Contributor

It seems like the method add_points_as_corners is called with an empty list of points, which it cannot handle and thus crashes.

If the x or y range of the Axes are changed the issue disapear in most cases.
The issue can also vanish if the function to plot is changed.

For the record, I modified VMobject.add_points_as_corners() in a relatively old PR: #3765. It seems I missed a validation for the empty case.

@henrikmidtiby
Copy link
Contributor Author

Do you mean that you are running a modified Manim with your commit? Because in an unmodified Manim 0.18.1 your example code does not crash...

Sorry, I forgot to mention that the code originated from an earlier animation I wrote using Manim 0.18.1.
When I tried to run it on the most recent version of the main branch, manim crashed.
After that I created a minimal example that triggered the crash, which is what was posted as this issue.

@chopan050
Copy link
Contributor

I just submitted a short PR fixing this.
The relevant information is the following, especially what I marked in bold:

In the earlier PR #3765, I optimized VMobject.add_points_as_corners() to allocate space for VMobject.points only once, instead of calling N times in a for loop the add_line_to() method which allocated space N times, one for each point. This is really helpful for drawing and animating multiple ParametricFunctions and/or ImplicitFunctions, which tend to require the computation of a lot of points which are then interpolated smoothly.

However, I missed the edge case in which the points parameter contains 0 points, which caused the crash described in #4090. It is possible that the ImplicitFunction algorithm for finding a sample of points belonging to the curve returns a single point for one or more branches (called curves) of the full implicit curve. In that case, the following three lines in ImplicitFunction.generate_points() will fail because of that mistake:

       for curve in curves:
           self.start_new_path(curve[0])
           self.add_points_as_corners(curve[1:])

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants