ManimCommunity / ManimCommunity/manim

`CurvesAsSubmobjects` should keep attributes of `ParametricFunction`

Open
#3,150 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

refactor
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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.