ManimCommunity / manim

A community-maintained Python framework for creating mathematical animations.
https://www.manim.community
MIT License
26.47k stars 1.82k forks source link

'RuntimeWarning: divide by zero encountered in scalar divide' causing Axes rendering failure for axis values 0 #3856

Closed hrmeetsingh closed 3 months ago

hrmeetsingh commented 4 months ago

Description of bug / unexpected behavior

When trying to render an Axes mobject, the code doesnt seem to handle 0 values for x_range/y_range. I am new to Manim and stumbled upon this exception(Not sure how you reached here, please file a bug report at https://github.com/ManimCommunity/manim/issues/new/choose) while trying different values.

Hope it helps

Expected behavior

I am expecting to not render the y axis at all by providing a (0,0,0) to the y_range for the Axes mobject, which should have been handled by the library

How to reproduce the issue

Code for reproducing the problem ```py # This code is running in a Jupyter Notebook cell, the only other cell run before this is for importing manim %%manim -qm -v WARNING DrawAxes class DrawAxes(Scene): def construct(self): axes = Axes((0,10,1),(0,0,0)) self.play(Create(axes), run_time=5) self.wait() ```

Additional media files

Images/GIFs Did not generate any media files

Logs

Terminal output ``` /Users/harmeetsingh/Documents/code/3b1bManim/manim/lib/python3.12/site-packages/manim/mobject/geometry/line.py:205: RuntimeWarning: divide by zero encountered in scalar divide return self.scale(length / self.get_length()) /Users/harmeetsingh/Documents/code/3b1bManim/manim/lib/python3.12/site-packages/manim/mobject/mobject.py:1222: RuntimeWarning: invalid value encountered in multiply lambda points: scale_factor * points, **kwargs --------------------------------------------------------------------------- Exception Traceback (most recent call last) Cell In[2], line 1 ----> 1 get_ipython().run_cell_magic('manim', '-qm -v WARNING DrawAxes', '\nclass DrawAxes(Scene):\n def construct(self):\n axes = Axes((0,10,1),(0,0,0))\n self.play(Create(axes), run_time=5)\n self.wait()\n') File ~/Documents/code/3b1bManim/manim/lib/python3.12/site-packages/IPython/core/interactiveshell.py:2541, in InteractiveShell.run_cell_magic(self, magic_name, line, cell) 2539 with self.builtin_trap: 2540 args = (magic_arg_s, cell) -> 2541 result = fn(*args, **kwargs) 2543 # The code below prevents the output from being displayed 2544 # when using magics with decorator @output_can_be_silenced 2545 # when the last Python token in the expression is a ';'. 2546 if getattr(fn, magic.MAGIC_OUTPUT_CAN_BE_SILENCED, False): File ~/Documents/code/3b1bManim/manim/lib/python3.12/site-packages/manim/utils/ipython_magic.py:143, in ManimMagic.manim(self, line, cell, local_ns) 141 SceneClass = local_ns[config["scene_names"][0]] 142 scene = SceneClass(renderer=renderer) --> 143 scene.render() 144 finally: 145 # Shader cache becomes invalid as the context is destroyed 146 shader_program_cache.clear() File ~/Documents/code/3b1bManim/manim/lib/python3.12/site-packages/manim/scene/scene.py:229, in Scene.render(self, preview) 227 self.setup() 228 try: --> 229 self.construct() 230 except EndSceneEarlyException: 231 pass File :4, in construct(self) File ~/Documents/code/3b1bManim/manim/lib/python3.12/site-packages/manim/mobject/graphing/coordinate_systems.py:1897, in Axes.__init__(self, x_range, y_range, x_length, y_length, axis_config, x_axis_config, y_axis_config, tips, **kwargs) 1894 self.y_axis_config["exclude_origin_tick"] = False 1896 self.x_axis = self._create_axis(self.x_range, self.x_axis_config, self.x_length) -> 1897 self.y_axis = self._create_axis(self.y_range, self.y_axis_config, self.y_length) 1899 # Add as a separate group in case various other 1900 # mobjects are added to self, as for example in 1901 # NumberPlane below 1902 self.axes = VGroup(self.x_axis, self.y_axis) File ~/Documents/code/3b1bManim/manim/lib/python3.12/site-packages/manim/mobject/graphing/coordinate_systems.py:1971, in Axes._create_axis(self, range_terms, axis_config, length) 1954 """Creates an axis and dynamically adjusts its position depending on where 0 is located on the line. 1955 1956 Parameters (...) 1968 Returns a number line based on ``range_terms``. 1969 """ 1970 axis_config["length"] = length -> 1971 axis = NumberLine(range_terms, **axis_config) 1973 # without the call to _origin_shift, graph does not exist when min > 0 or max < 0 1974 # shifts the axis so that 0 is centered 1975 axis.shift(-axis.number_to_point(self._origin_shift([axis.x_min, axis.x_max]))) File ~/Documents/code/3b1bManim/manim/lib/python3.12/site-packages/manim/mobject/graphing/number_line.py:231, in NumberLine.__init__(self, x_range, length, unit_size, include_ticks, tick_size, numbers_with_elongated_ticks, longer_tick_multiple, exclude_origin_tick, rotation, stroke_width, include_tip, tip_width, tip_height, tip_shape, include_numbers, font_size, label_direction, label_constructor, scaling, line_to_number_buff, decimal_number_config, numbers_to_exclude, numbers_to_include, **kwargs) 228 self.center() 230 if self.include_tip: --> 231 self.add_tip( 232 tip_length=self.tip_height, 233 tip_width=self.tip_width, 234 tip_shape=tip_shape, 235 ) 236 self.tip.set_stroke(self.stroke_color, self.stroke_width) 238 if self.include_ticks: File ~/Documents/code/3b1bManim/manim/lib/python3.12/site-packages/manim/mobject/geometry/arc.py:121, in TipableVMobject.add_tip(self, tip, tip_shape, tip_length, tip_width, at_start) 119 else: 120 self.position_tip(tip, at_start) --> 121 self.reset_endpoints_based_on_tip(tip, at_start) 122 self.asign_tip_attr(tip, at_start) 123 self.add(tip) File ~/Documents/code/3b1bManim/manim/lib/python3.12/site-packages/manim/mobject/geometry/arc.py:204, in TipableVMobject.reset_endpoints_based_on_tip(self, tip, at_start) 202 self.put_start_and_end_on(tip.base, self.get_end()) 203 else: --> 204 self.put_start_and_end_on(self.get_start(), tip.base) 205 return self File ~/Documents/code/3b1bManim/manim/lib/python3.12/site-packages/manim/mobject/geometry/tips.py:133, in ArrowTip.base(self) 117 @property 118 def base(self) -> Point3D: 119 r"""The base point of the arrow tip. 120 121 This is the point connecting to the arrow line. (...) 131 132 """ --> 133 return self.point_from_proportion(0.5) File ~/Documents/code/3b1bManim/manim/lib/python3.12/site-packages/manim/mobject/types/vectorized_mobject.py:1451, in VMobject.point_from_proportion(self, alpha) 1448 return curve(residue) 1450 current_length += length -> 1451 raise Exception( 1452 "Not sure how you reached here, please file a bug report at https://github.com/ManimCommunity/manim/issues/new/choose" 1453 ) Exception: Not sure how you reached here, please file a bug report at https://github.com/ManimCommunity/manim/issues/new/choose ```

System specifications

System Details - OS (with version, e.g., Windows 10 v2004 or macOS 10.15 (Catalina)): MacOS Sonoma 14.5 (Apple MacBook M3 Pro) - RAM: 18Gb - Python version (`python/py/python3 --version`): Python 3.12.0 - Installed modules (provide output from `pip list`): ``` Package Version ------------------------- -------------- anyio 4.4.0 appnope 0.1.4 argon2-cffi 23.1.0 argon2-cffi-bindings 21.2.0 arrow 1.3.0 asttokens 2.4.1 async-lru 2.0.4 attrs 23.2.0 Babel 2.15.0 beautifulsoup4 4.12.3 bleach 6.1.0 certifi 2024.7.4 cffi 1.16.0 charset-normalizer 3.3.2 click 8.1.7 cloup 3.0.5 comm 0.2.2 Cython 3.0.10 debugpy 1.8.2 decorator 5.1.1 defusedxml 0.7.1 executing 2.0.1 fastjsonschema 2.20.0 fqdn 1.5.1 glcontext 2.5.0 h11 0.14.0 httpcore 1.0.5 httpx 0.27.0 idna 3.7 ipykernel 6.29.5 ipython 8.26.0 isoduration 20.11.0 isosurfaces 0.1.2 jedi 0.19.1 Jinja2 3.1.4 json5 0.9.25 jsonpointer 3.0.0 jsonschema 4.23.0 jsonschema-specifications 2023.12.1 jupyter_client 8.6.2 jupyter_core 5.7.2 jupyter-events 0.10.0 jupyter-lsp 2.2.5 jupyter_server 2.14.2 jupyter_server_terminals 0.5.3 jupyterlab 4.2.3 jupyterlab_pygments 0.3.0 jupyterlab_server 2.27.2 manim 0.18.1 ManimPango 0.5.0 mapbox-earcut 1.0.1 markdown-it-py 3.0.0 MarkupSafe 2.1.5 matplotlib-inline 0.1.7 mdurl 0.1.2 mistune 3.0.2 moderngl 5.10.0 moderngl-window 2.4.6 multipledispatch 1.0.0 nbclient 0.10.0 nbconvert 7.16.4 nbformat 5.10.4 nest-asyncio 1.6.0 networkx 3.3 notebook 7.2.1 notebook_shim 0.2.4 numpy 1.26.4 overrides 7.7.0 packaging 24.1 pandocfilters 1.5.1 parso 0.8.4 pexpect 4.9.0 pillow 10.4.0 pip 24.1.2 platformdirs 4.2.2 prometheus_client 0.20.0 prompt_toolkit 3.0.47 psutil 6.0.0 ptyprocess 0.7.0 pure-eval 0.2.2 pycairo 1.26.1 pycparser 2.22 pydub 0.25.1 pyglet 2.0.16 Pygments 2.18.0 pyobjc-core 10.3.1 pyobjc-framework-Cocoa 10.3.1 pyrr 0.10.3 python-dateutil 2.9.0.post0 python-json-logger 2.0.7 PyYAML 6.0.1 pyzmq 26.0.3 referencing 0.35.1 requests 2.32.3 rfc3339-validator 0.1.4 rfc3986-validator 0.1.1 rich 13.7.1 rpds-py 0.19.0 scipy 1.14.0 screeninfo 0.8.1 Send2Trash 1.8.3 setuptools 70.3.0 six 1.16.0 skia-pathops 0.8.0.post1 sniffio 1.3.1 soupsieve 2.5 srt 3.5.3 stack-data 0.6.3 svgelements 1.9.6 terminado 0.18.1 tinycss2 1.3.0 tornado 6.4.1 tqdm 4.66.4 traitlets 5.14.3 types-python-dateutil 2.9.0.20240316 typing_extensions 4.12.2 uri-template 1.3.0 urllib3 2.2.2 watchdog 4.0.1 wcwidth 0.2.13 webcolors 24.6.0 webencodings 0.5.1 websocket-client 1.8.0 ```
LaTeX details + LaTeX distribution (e.g. TeX Live 2020): I do not have a MacTex installation on this machine, the non zero values run and render the program. I can check again with the MacTex installed if needed + Installed LaTeX packages:

Additional comments

Screenshot -

Screenshot 2024-07-13 at 3 50 38 PM
behackl commented 4 months ago

Hmm, Axes is by default a two-dimensional coordinate system. If you just want one dimension, you should use a NumberLine instead.

The case of passing a "0-lengthx or y range toAxes` is somewhat odd, I am not sure it is worth to investigate how a clean solution for it can be implemented.

hrmeetsingh commented 4 months ago

Hmm, Axes is by default a two-dimensional coordinate system. If you just want one dimension, you should use a NumberLine instead.

The case of passing a "0-lengthx or y range toAxes` is somewhat odd, I am not sure it is worth to investigate how a clean solution for it can be implemented.

Thanks for the suggestion @behackl , will be reading further on this as I have just started using the tool and was for sure not aware of the clean way of doing it. Reading the exception message felt that it will be good to report the edge case.

Can think of a scenario where the axes values are dynamically calculated based on some logic and are used to define Axes mobject. it's possible to hit this exception again if the values come out to be 0 at runtime

JasonGrace2282 commented 4 months ago

The case of passing a "0-lengthx or y range toAxes` is somewhat odd, I am not sure it is worth to investigate how a clean solution for it can be implemented.

Can we just raise an exception in the __init__, so that there is a better error message? Something like

x0, x, dx = x_range
if 0 in (dx, x0+x):
    raise ValueError("Axes does not handle x_range's of 0, maybe you wanted to use NumberLine instead?")