ManimCommunity / ManimCommunity/manim
`CurvesAsSubmobjects` should keep attributes of `ParametricFunction`
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 40.9k
- Forks
- 3.1k
- Avg merge
- 3d 12h
- Merged PRs (30d)
- 25
Description
## Description of bug / unexpected behavior
When applying `CurvesAsSubmobjects` to a `ParametricFunction`, the attributes of `ParametricFunction` are no longer available. This means that the new curve cannot be used with many of the methods typically used with curves, like `input_to_graph_point`.
## Expected behavior
`CurvesAsSubmobjects` should preserve the attributes of `ParametricFunction`, such as `.function` and `.t_range`.
## How to reproduce the issue
Code for reproducing the problem
```py
from manim import *
class CurveExample(Scene):
def construct(self):
axes = Axes(
x_range=[0, 6],
y_range=[-2, 2],
tips=False,
)
curve = axes.plot(
lambda x: 2 * np.sin(x), x_range=(0.0, 6, 0.001), color=BLUE
)
new_curve = CurvesAsSubmobjects(curve)
curve_dot = Dot(axes.input_to_graph_point(1, new_curve), color=ORANGE)
self.add(axes, new_curve, curve_dot)
```
## Logs
Terminal output
```
Manim Community v0.17.2
╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮
│ /home/alexlembcke/.local/lib/python3.10/site-packages/manim/cli/render/commands.py:115 in render │
│ │
│ 112 │ │ │ try: │
│ 113 │ │ │ │ with tempconfig({}): │
│ 114 │ │ │ │ │ scene = SceneClass() │
│ ❱ 115 │ │ │ │ │ scene.render() │
│ 116 │ │ │ except Exception: │
│ 117 │ │ │ │ error_console.print_exception() │
│ 118 │ │ │ │ sys.exit(1) │
│ │
│ /home/alexlembcke/.local/lib/python3.10/site-packages/manim/scene/scene.py:223 in render │
│ │
│ 220 │ │ """ │
│ 221 │ │ self.setup() │
│ 222 │ │ try: │
│ ❱ 223 │ │ │ self.construct() │
│ 224 │ │ except EndSceneEarlyException: │
│ 225 │ │ │ pass │
│ 226 │ │ except RerunSceneException as e: │
│ │
│ /home/alexlembcke/ManimDev/plot_colorscale.py:17 in construct │
│ │
│ 14 │ │ │
│ 15 │ │ new_curve = CurvesAsSubmobjects(curve) │
│ 16 │ │ │
│ ❱ 17 │ │ curve_dot = Dot(axes.input_to_graph_point(1, new_curve), color=ORANGE) │
│ 18 │ │ │
│ 19 │ │ self.add(axes, new_curve, curve_dot) │
│ 20 │
│ │
│ /home/alexlembcke/.local/lib/python3.10/site-packages/manim/mobject/graphing/coordinate_systems. │
│ py:991 in input_to_graph_point │
│ │
│ 988 │ │ if hasattr(graph, "underlying_function"): │
│ 989 │ │ │ return graph.function(x) │
│ 990 │ │ else: │
│ ❱ 991 │ │ │ alpha = binary_search( │
│ 992 │ │ │ │ function=lambda a: self.point_to_coords(graph.point_from_proportion(a))[ │
│ 993 │ │ │ │ │ 0 │
│ 994 │ │ │ │ ], │
│ │
│ /home/alexlembcke/.local/lib/python3.10/site-packages/manim/utils/simple_functions.py:63 in │
│ binary_search │
│ │
│ 60 │ mh = np.mean(np.array([lh, rh])) │
│ 61 │ while abs(rh - lh) > tolerance: │
│ 62 │ │ mh = np.mean(np.array([lh, rh])) │
│ ❱ 63 │ │ lx, mx, rx = (function(h) for h in (lh, mh, rh)) │
│ 64 │ │ if lx == target: │
│ 65 │ │ │ return lh │
│ 66 │ │ if rx == target: │
│ │
│ /home/alexlembcke/.local/lib/python3.10/site-packages/manim/utils/simple_functions.py:63 in │
│ │
│ │
│ 60 │ mh = np.mean(np.array([lh, rh])) │
│ 61 │ while abs(rh - lh) > tolerance: │
│ 62 │ │ mh = np.mean(np.array([lh, rh])) │
│ ❱ 63 │ │ lx, mx, rx = (function(h) for h in (lh, mh, rh)) │
│ 64 │ │ if lx == target: │
│ 65 │ │ │ return lh │
│ 66 │ │ if rx == target: │
│ │
│ /home/alexlembcke/.local/lib/python3.10/site-packages/manim/mobject/graphing/coordinate_systems. │
│ py:992 in │
│ │
│ 989 │ │ │ return graph.function(x) │
│ 990 │ │ else: │
│ 991 │ │ │ alpha = binary_search( │
│ ❱ 992 │ │ │ │ function=lambda a: self.point_to_coords(graph.point_from_proportion(a))[ │
│ 993 │ │ │ │ │ 0 │
│ 994 │ │ │ │ ], │
│ 995 │ │ │ │ target=x, │
│ │
│ /home/alexlembcke/.local/lib/python3.10/site-packages/manim/mobject/types/vectorized_mobject.py: │
│ 1284 in point_from_proportion │
│ │
│ 1281 │ │ if alpha < 0 or alpha > 1: │
│ 1282 │ │ │ raise ValueError(f"Alpha {alpha} not between 0 and 1.") │
│ 1283 │ │ │
│ ❱ 1284 │ │ self.throw_error_if_no_points() │
│ 1285 │ │ if alpha == 1: │
│ 1286 │ │ │ return self.points[-1] │
│ 1287 │
│ │
│ /home/alexlembcke/.local/lib/python3.10/site-packages/manim/mobject/mobject.py:2731 in │
│ throw_error_if_no_points │
│ │
│ 2728 │ def throw_error_if_no_points(self): │
│ 2729 │ │ if self.has_no_points(): │
│ 2730 │ │ │ caller_name = sys._getframe(1).f_code.co_name │
│ ❱ 2731 │ │ │ raise Exception( │
│ 2732 │ │ │ │ f"Cannot call Mobject.{caller_name} for a Mobject with no points", │
│ 2733 │ │ │ ) │
│ 2734 │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
Exception: Cannot call Mobject.point_from_proportion for a Mobject with no points
```
## System specifications
System Details
- OS: Ubuntu 22.10
- RAM: 32GB
- Python version (`python/py/python3 --version`): Python 3.10.7
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by locating CurvesAsSubmobjects and ParametricFunction, then reproduce the failure with the Axes, ParametricFunction, and input_to_graph_point example in the issue. Preserve the ParametricFunction attributes, including function and t_range, so the resulting curve supports the demonstrated graph lookup without raising the no-points exception.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- computer-graphics
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 42/100