manim 0.17.3__py3-none-any.whl → 0.18.0.post0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of manim might be problematic. Click here for more details.

Files changed (84) hide show
  1. manim/__init__.py +1 -0
  2. manim/__main__.py +2 -0
  3. manim/_config/__init__.py +0 -1
  4. manim/_config/logger_utils.py +1 -0
  5. manim/_config/utils.py +14 -5
  6. manim/animation/changing.py +9 -5
  7. manim/animation/creation.py +8 -3
  8. manim/animation/indication.py +4 -4
  9. manim/animation/speedmodifier.py +2 -4
  10. manim/animation/updaters/mobject_update_utils.py +134 -16
  11. manim/camera/camera.py +31 -17
  12. manim/cli/checkhealth/__init__.py +0 -0
  13. manim/cli/checkhealth/checks.py +173 -0
  14. manim/cli/checkhealth/commands.py +81 -0
  15. manim/cli/render/global_options.py +6 -0
  16. manim/constants.py +58 -54
  17. manim/mobject/geometry/__init__.py +1 -0
  18. manim/mobject/geometry/arc.py +126 -91
  19. manim/mobject/geometry/boolean_ops.py +6 -10
  20. manim/mobject/geometry/labeled.py +155 -0
  21. manim/mobject/geometry/line.py +66 -50
  22. manim/mobject/geometry/polygram.py +23 -15
  23. manim/mobject/geometry/shape_matchers.py +24 -15
  24. manim/mobject/geometry/tips.py +62 -40
  25. manim/mobject/graph.py +3 -4
  26. manim/mobject/graphing/coordinate_systems.py +190 -139
  27. manim/mobject/graphing/number_line.py +5 -2
  28. manim/mobject/graphing/probability.py +4 -3
  29. manim/mobject/graphing/scale.py +7 -7
  30. manim/mobject/logo.py +108 -22
  31. manim/mobject/matrix.py +33 -37
  32. manim/mobject/mobject.py +327 -260
  33. manim/mobject/opengl/opengl_image_mobject.py +1 -1
  34. manim/mobject/opengl/opengl_mobject.py +18 -12
  35. manim/mobject/opengl/opengl_point_cloud_mobject.py +1 -1
  36. manim/mobject/opengl/opengl_surface.py +1 -1
  37. manim/mobject/opengl/opengl_vectorized_mobject.py +21 -17
  38. manim/mobject/svg/brace.py +3 -1
  39. manim/mobject/svg/svg_mobject.py +9 -11
  40. manim/mobject/table.py +50 -54
  41. manim/mobject/text/numbers.py +48 -6
  42. manim/mobject/text/tex_mobject.py +8 -12
  43. manim/mobject/text/text_mobject.py +32 -24
  44. manim/mobject/three_d/three_d_utils.py +13 -8
  45. manim/mobject/three_d/three_dimensions.py +61 -43
  46. manim/mobject/types/image_mobject.py +5 -4
  47. manim/mobject/types/point_cloud_mobject.py +8 -6
  48. manim/mobject/types/vectorized_mobject.py +385 -258
  49. manim/mobject/vector_field.py +19 -11
  50. manim/plugins/import_plugins.py +1 -1
  51. manim/plugins/plugins_flags.py +1 -6
  52. manim/renderer/shader.py +2 -2
  53. manim/scene/scene.py +15 -7
  54. manim/scene/scene_file_writer.py +1 -2
  55. manim/scene/three_d_scene.py +1 -1
  56. manim/scene/vector_space_scene.py +17 -7
  57. manim/typing.py +133 -0
  58. manim/utils/bezier.py +267 -83
  59. manim/utils/color/AS2700.py +234 -0
  60. manim/utils/color/BS381.py +315 -0
  61. manim/utils/color/X11.py +530 -0
  62. manim/utils/color/XKCD.py +949 -0
  63. manim/utils/color/__init__.py +58 -0
  64. manim/utils/color/core.py +1036 -0
  65. manim/utils/color/manim_colors.py +220 -0
  66. manim/utils/docbuild/autocolor_directive.py +92 -0
  67. manim/utils/docbuild/manim_directive.py +40 -6
  68. manim/utils/file_ops.py +1 -1
  69. manim/utils/hashing.py +1 -1
  70. manim/utils/iterables.py +1 -1
  71. manim/utils/rate_functions.py +33 -0
  72. manim/utils/simple_functions.py +0 -18
  73. manim/utils/space_ops.py +55 -42
  74. manim/utils/testing/frames_comparison.py +9 -0
  75. manim/utils/tex.py +2 -0
  76. manim/utils/tex_file_writing.py +29 -2
  77. {manim-0.17.3.dist-info → manim-0.18.0.post0.dist-info}/METADATA +14 -14
  78. {manim-0.17.3.dist-info → manim-0.18.0.post0.dist-info}/RECORD +82 -71
  79. {manim-0.17.3.dist-info → manim-0.18.0.post0.dist-info}/WHEEL +1 -1
  80. manim/communitycolors.py +0 -9
  81. manim/utils/color.py +0 -552
  82. {manim-0.17.3.dist-info → manim-0.18.0.post0.dist-info}/LICENSE +0 -0
  83. {manim-0.17.3.dist-info → manim-0.18.0.post0.dist-info}/LICENSE.community +0 -0
  84. {manim-0.17.3.dist-info → manim-0.18.0.post0.dist-info}/entry_points.txt +0 -0
@@ -14,10 +14,10 @@ __all__ = [
14
14
 
15
15
  import fractions as fr
16
16
  import numbers
17
- from typing import TYPE_CHECKING, Any, Callable, Iterable, Sequence
17
+ from typing import TYPE_CHECKING, Any, Callable, Iterable, Sequence, TypeVar, overload
18
18
 
19
19
  import numpy as np
20
- from colour import Color
20
+ from typing_extensions import Self
21
21
 
22
22
  from manim import config
23
23
  from manim.constants import *
@@ -44,6 +44,8 @@ from manim.utils.color import (
44
44
  GREEN,
45
45
  WHITE,
46
46
  YELLOW,
47
+ ManimColor,
48
+ ParsableManimColor,
47
49
  color_gradient,
48
50
  invert_color,
49
51
  )
@@ -53,6 +55,9 @@ from manim.utils.space_ops import angle_of_vector
53
55
 
54
56
  if TYPE_CHECKING:
55
57
  from manim.mobject.mobject import Mobject
58
+ from manim.typing import ManimFloat, Point2D, Point3D, Vector3
59
+
60
+ LineType = TypeVar("LineType", bound=Line)
56
61
 
57
62
 
58
63
  class CoordinateSystem:
@@ -107,12 +112,12 @@ class CoordinateSystem:
107
112
 
108
113
  def __init__(
109
114
  self,
110
- x_range=None,
111
- y_range=None,
112
- x_length=None,
113
- y_length=None,
114
- dimension=2,
115
- ):
115
+ x_range: Sequence[float] | None = None,
116
+ y_range: Sequence[float] | None = None,
117
+ x_length: float | None = None,
118
+ y_length: float | None = None,
119
+ dimension: int = 2,
120
+ ) -> None:
116
121
  self.dimension = dimension
117
122
 
118
123
  default_step = 1
@@ -140,13 +145,13 @@ class CoordinateSystem:
140
145
  self.y_length = y_length
141
146
  self.num_sampled_graph_points_per_tick = 10
142
147
 
143
- def coords_to_point(self, *coords):
148
+ def coords_to_point(self, *coords: Sequence[ManimFloat]):
144
149
  raise NotImplementedError()
145
150
 
146
- def point_to_coords(self, point):
151
+ def point_to_coords(self, point: Point3D):
147
152
  raise NotImplementedError()
148
153
 
149
- def polar_to_point(self, radius: float, azimuth: float) -> np.ndarray:
154
+ def polar_to_point(self, radius: float, azimuth: float) -> Point2D:
150
155
  r"""Gets a point from polar coordinates.
151
156
 
152
157
  Parameters
@@ -177,7 +182,7 @@ class CoordinateSystem:
177
182
  """
178
183
  return self.coords_to_point(radius * np.cos(azimuth), radius * np.sin(azimuth))
179
184
 
180
- def point_to_polar(self, point: np.ndarray) -> tuple[float, float]:
185
+ def point_to_polar(self, point: np.ndarray) -> Point2D:
181
186
  r"""Gets polar coordinates from a point.
182
187
 
183
188
  Parameters
@@ -193,11 +198,13 @@ class CoordinateSystem:
193
198
  x, y = self.point_to_coords(point)
194
199
  return np.sqrt(x**2 + y**2), np.arctan2(y, x)
195
200
 
196
- def c2p(self, *coords):
201
+ def c2p(
202
+ self, *coords: float | Sequence[float] | Sequence[Sequence[float]] | np.ndarray
203
+ ) -> np.ndarray:
197
204
  """Abbreviation for :meth:`coords_to_point`"""
198
205
  return self.coords_to_point(*coords)
199
206
 
200
- def p2c(self, point):
207
+ def p2c(self, point: Point3D):
201
208
  """Abbreviation for :meth:`point_to_coords`"""
202
209
  return self.point_to_coords(point)
203
210
 
@@ -212,7 +219,7 @@ class CoordinateSystem:
212
219
  def get_axes(self):
213
220
  raise NotImplementedError()
214
221
 
215
- def get_axis(self, index):
222
+ def get_axis(self, index: int) -> Mobject:
216
223
  return self.get_axes()[index]
217
224
 
218
225
  def get_origin(self) -> np.ndarray:
@@ -225,19 +232,19 @@ class CoordinateSystem:
225
232
  """
226
233
  return self.coords_to_point(0, 0)
227
234
 
228
- def get_x_axis(self):
235
+ def get_x_axis(self) -> Mobject:
229
236
  return self.get_axis(0)
230
237
 
231
- def get_y_axis(self):
238
+ def get_y_axis(self) -> Mobject:
232
239
  return self.get_axis(1)
233
240
 
234
- def get_z_axis(self):
241
+ def get_z_axis(self) -> Mobject:
235
242
  return self.get_axis(2)
236
243
 
237
- def get_x_unit_size(self):
244
+ def get_x_unit_size(self) -> float:
238
245
  return self.get_x_axis().get_unit_size()
239
246
 
240
- def get_y_unit_size(self):
247
+ def get_y_unit_size(self) -> float:
241
248
  return self.get_y_axis().get_unit_size()
242
249
 
243
250
  def get_x_axis_label(
@@ -290,7 +297,7 @@ class CoordinateSystem:
290
297
  direction: Sequence[float] = UP * 0.5 + RIGHT,
291
298
  buff: float = SMALL_BUFF,
292
299
  **kwargs,
293
- ):
300
+ ) -> Mobject:
294
301
  """Generate a y-axis label.
295
302
 
296
303
  Parameters
@@ -369,9 +376,9 @@ class CoordinateSystem:
369
376
 
370
377
  def add_coordinates(
371
378
  self,
372
- *axes_numbers: (Iterable[float] | None | dict[float, str | float | Mobject]),
373
- **kwargs,
374
- ):
379
+ *axes_numbers: Iterable[float] | None | dict[float, str | float | Mobject],
380
+ **kwargs: Any,
381
+ ) -> Self:
375
382
  """Adds labels to the axes. Use ``Axes.coordinate_labels`` to
376
383
  access the coordinates after creation.
377
384
 
@@ -425,15 +432,39 @@ class CoordinateSystem:
425
432
 
426
433
  return self
427
434
 
435
+ # overload necessary until https://github.com/python/mypy/issues/3737 is supported
436
+ @overload
428
437
  def get_line_from_axis_to_point(
429
438
  self,
430
439
  index: int,
431
440
  point: Sequence[float],
432
- line_func: Line = DashedLine,
433
- line_config: dict | None = None,
434
- color: Color | None = None,
435
- stroke_width: float = 2,
436
- ) -> Line:
441
+ line_config: dict | None = ...,
442
+ color: ParsableManimColor | None = ...,
443
+ stroke_width: float = ...,
444
+ ) -> DashedLine:
445
+ ...
446
+
447
+ @overload
448
+ def get_line_from_axis_to_point(
449
+ self,
450
+ index: int,
451
+ point: Sequence[float],
452
+ line_func: type[LineType],
453
+ line_config: dict | None = ...,
454
+ color: ParsableManimColor | None = ...,
455
+ stroke_width: float = ...,
456
+ ) -> LineType:
457
+ ...
458
+
459
+ def get_line_from_axis_to_point( # type: ignore[no-untyped-def]
460
+ self,
461
+ index,
462
+ point,
463
+ line_func=DashedLine,
464
+ line_config=None,
465
+ color=None,
466
+ stroke_width=2,
467
+ ):
437
468
  """Returns a straight line from a given axis to a point in the scene.
438
469
 
439
470
  Parameters
@@ -467,14 +498,14 @@ class CoordinateSystem:
467
498
  if color is None:
468
499
  color = VMobject().color
469
500
 
470
- line_config["color"] = color
501
+ line_config["color"] = ManimColor.parse(color)
471
502
  line_config["stroke_width"] = stroke_width
472
503
 
473
504
  axis = self.get_axis(index)
474
505
  line = line_func(axis.get_projection(point), point, **line_config)
475
506
  return line
476
507
 
477
- def get_vertical_line(self, point: Sequence[float], **kwargs) -> Line:
508
+ def get_vertical_line(self, point: Sequence[float], **kwargs: Any) -> Line:
478
509
  """A vertical line from the x-axis to a given point in the scene.
479
510
 
480
511
  Parameters
@@ -588,8 +619,8 @@ class CoordinateSystem:
588
619
  function: Callable[[float], float],
589
620
  x_range: Sequence[float] | None = None,
590
621
  use_vectorized: bool = False,
591
- **kwargs,
592
- ):
622
+ **kwargs: Any,
623
+ ) -> ParametricFunction:
593
624
  """Generates a curve based on a function.
594
625
 
595
626
  Parameters
@@ -684,10 +715,10 @@ class CoordinateSystem:
684
715
 
685
716
  def plot_implicit_curve(
686
717
  self,
687
- func: Callable,
718
+ func: Callable[[float, float], float],
688
719
  min_depth: int = 5,
689
720
  max_quads: int = 1500,
690
- **kwargs,
721
+ **kwargs: Any,
691
722
  ) -> ImplicitFunction:
692
723
  """Creates the curves of an implicit function.
693
724
 
@@ -736,7 +767,7 @@ class CoordinateSystem:
736
767
  self,
737
768
  function: Callable[[float], np.ndarray],
738
769
  use_vectorized: bool = False,
739
- **kwargs,
770
+ **kwargs: Any,
740
771
  ) -> ParametricFunction:
741
772
  """A parametric curve.
742
773
 
@@ -783,8 +814,8 @@ class CoordinateSystem:
783
814
  def plot_polar_graph(
784
815
  self,
785
816
  r_func: Callable[[float], float],
786
- theta_range: Sequence[float] = [0, 2 * PI],
787
- **kwargs,
817
+ theta_range: Sequence[float] | None = None,
818
+ **kwargs: Any,
788
819
  ) -> ParametricFunction:
789
820
  """A polar graph.
790
821
 
@@ -810,6 +841,7 @@ class CoordinateSystem:
810
841
  graph = plane.plot_polar_graph(r, [0, 2 * PI], color=ORANGE)
811
842
  self.add(plane, graph)
812
843
  """
844
+ theta_range = theta_range if theta_range is not None else [0, 2 * PI]
813
845
  graph = ParametricFunction(
814
846
  function=lambda th: self.pr2pt(r_func(th), th),
815
847
  t_range=theta_range,
@@ -823,10 +855,12 @@ class CoordinateSystem:
823
855
  function: Callable[[float], float],
824
856
  u_range: Sequence[float] | None = None,
825
857
  v_range: Sequence[float] | None = None,
826
- colorscale: Sequence[[color], float] | None = None,
858
+ colorscale: Sequence[ParsableManimColor]
859
+ | Sequence[tuple[ParsableManimColor, float]]
860
+ | None = None,
827
861
  colorscale_axis: int = 2,
828
- **kwargs,
829
- ):
862
+ **kwargs: Any,
863
+ ) -> Surface | OpenGLSurface:
830
864
  """Generates a surface based on a function.
831
865
 
832
866
  Parameters
@@ -961,7 +995,9 @@ class CoordinateSystem:
961
995
  f"x={x} not located in the range of the graph ([{self.p2c(graph.get_start())[0]}, {self.p2c(graph.get_end())[0]}])",
962
996
  )
963
997
 
964
- def input_to_graph_coords(self, x: float, graph: ParametricFunction) -> tuple:
998
+ def input_to_graph_coords(
999
+ self, x: float, graph: ParametricFunction
1000
+ ) -> tuple[float, float]:
965
1001
  """Returns a tuple of the axis relative coordinates of the point
966
1002
  on the graph based on the x-value given.
967
1003
 
@@ -977,7 +1013,7 @@ class CoordinateSystem:
977
1013
  """
978
1014
  return x, graph.underlying_function(x)
979
1015
 
980
- def i2gc(self, x: float, graph: ParametricFunction) -> tuple:
1016
+ def i2gc(self, x: float, graph: ParametricFunction) -> tuple[float, float]:
981
1017
  """Alias for :meth:`input_to_graph_coords`."""
982
1018
  return self.input_to_graph_coords(x, graph)
983
1019
 
@@ -992,9 +1028,9 @@ class CoordinateSystem:
992
1028
  x_val: float | None = None,
993
1029
  direction: Sequence[float] = RIGHT,
994
1030
  buff: float = MED_SMALL_BUFF,
995
- color: Color | None = None,
1031
+ color: ParsableManimColor | None = None,
996
1032
  dot: bool = False,
997
- dot_config: dict | None = None,
1033
+ dot_config: dict[str, Any] | None = None,
998
1034
  ) -> Mobject:
999
1035
  """Creates a properly positioned label for the passed graph, with an optional dot.
1000
1036
 
@@ -1044,7 +1080,8 @@ class CoordinateSystem:
1044
1080
 
1045
1081
  if dot_config is None:
1046
1082
  dot_config = {}
1047
- color = color or graph.get_color()
1083
+ if color is None:
1084
+ color = graph.get_color()
1048
1085
  label = self.x_axis._create_label_tex(label).set_color(color)
1049
1086
 
1050
1087
  if x_val is None:
@@ -1074,9 +1111,9 @@ class CoordinateSystem:
1074
1111
  dx: float | None = 0.1,
1075
1112
  input_sample_type: str = "left",
1076
1113
  stroke_width: float = 1,
1077
- stroke_color: Color = BLACK,
1114
+ stroke_color: ParsableManimColor = BLACK,
1078
1115
  fill_opacity: float = 1,
1079
- color: Iterable[Color] | Color = np.array((BLUE, GREEN)),
1116
+ color: Iterable[ParsableManimColor] | ParsableManimColor = (BLUE, GREEN),
1080
1117
  show_signed_area: bool = True,
1081
1118
  bounded_graph: ParametricFunction = None,
1082
1119
  blend: bool = False,
@@ -1175,11 +1212,12 @@ class CoordinateSystem:
1175
1212
  rectangles = VGroup()
1176
1213
  x_range = np.arange(*x_range)
1177
1214
 
1178
- # allows passing a string to color the graph
1179
- if type(color) is str:
1180
- colors = [color] * len(x_range)
1215
+ if isinstance(color, (list, tuple)):
1216
+ color = [ManimColor(c) for c in color]
1181
1217
  else:
1182
- colors = color_gradient(color, len(x_range))
1218
+ color = [ManimColor(color)]
1219
+
1220
+ colors = color_gradient(color, len(x_range))
1183
1221
 
1184
1222
  for x, color in zip(x_range, colors):
1185
1223
  if input_sample_type == "left":
@@ -1234,11 +1272,11 @@ class CoordinateSystem:
1234
1272
  self,
1235
1273
  graph: ParametricFunction,
1236
1274
  x_range: tuple[float, float] | None = None,
1237
- color: Color | Iterable[Color] = [BLUE, GREEN],
1275
+ color: ParsableManimColor | Iterable[ParsableManimColor] = (BLUE, GREEN),
1238
1276
  opacity: float = 0.3,
1239
1277
  bounded_graph: ParametricFunction = None,
1240
- **kwargs,
1241
- ):
1278
+ **kwargs: Any,
1279
+ ) -> Polygon:
1242
1280
  """Returns a :class:`~.Polygon` representing the area under the graph passed.
1243
1281
 
1244
1282
  Parameters
@@ -1354,7 +1392,9 @@ class CoordinateSystem:
1354
1392
  p1 = np.array([*self.input_to_graph_coords(x + dx, graph)])
1355
1393
  return angle_of_vector(p1 - p0)
1356
1394
 
1357
- def slope_of_tangent(self, x: float, graph: ParametricFunction, **kwargs) -> float:
1395
+ def slope_of_tangent(
1396
+ self, x: float, graph: ParametricFunction, **kwargs: Any
1397
+ ) -> float:
1358
1398
  """Returns the slope of the tangent to the plotted curve
1359
1399
  at a particular x-value.
1360
1400
 
@@ -1383,7 +1423,7 @@ class CoordinateSystem:
1383
1423
  return np.tan(self.angle_of_tangent(x, graph, **kwargs))
1384
1424
 
1385
1425
  def plot_derivative_graph(
1386
- self, graph: ParametricFunction, color: Color = GREEN, **kwargs
1426
+ self, graph: ParametricFunction, color: ParsableManimColor = GREEN, **kwargs
1387
1427
  ) -> ParametricFunction:
1388
1428
  """Returns the curve of the derivative of the passed graph.
1389
1429
 
@@ -1432,8 +1472,8 @@ class CoordinateSystem:
1432
1472
  y_intercept: float = 0,
1433
1473
  samples: int = 50,
1434
1474
  use_vectorized: bool = False,
1435
- **kwargs,
1436
- ):
1475
+ **kwargs: Any,
1476
+ ) -> ParametricFunction:
1437
1477
  """Plots an antiderivative graph.
1438
1478
 
1439
1479
  Parameters
@@ -1491,12 +1531,12 @@ class CoordinateSystem:
1491
1531
  x: float,
1492
1532
  graph: ParametricFunction,
1493
1533
  dx: float | None = None,
1494
- dx_line_color: Color = YELLOW,
1495
- dy_line_color: Color | None = None,
1534
+ dx_line_color: ParsableManimColor = YELLOW,
1535
+ dy_line_color: ParsableManimColor | None = None,
1496
1536
  dx_label: float | str | None = None,
1497
1537
  dy_label: float | str | None = None,
1498
1538
  include_secant_line: bool = True,
1499
- secant_line_color: Color = GREEN,
1539
+ secant_line_color: ParsableManimColor = GREEN,
1500
1540
  secant_line_length: float = 10,
1501
1541
  ) -> VGroup:
1502
1542
  """Creates two lines representing `dx` and `df`, the labels for `dx` and `df`, and
@@ -1614,7 +1654,7 @@ class CoordinateSystem:
1614
1654
  graph: ParametricFunction,
1615
1655
  x_range: Sequence[float] | None = None,
1616
1656
  num_lines: int = 20,
1617
- **kwargs,
1657
+ **kwargs: Any,
1618
1658
  ) -> VGroup:
1619
1659
  """Obtains multiple lines from the x-axis to the curve.
1620
1660
 
@@ -1670,11 +1710,11 @@ class CoordinateSystem:
1670
1710
  x_val: float,
1671
1711
  graph: ParametricFunction,
1672
1712
  label: float | str | Mobject | None = None,
1673
- label_color: Color | None = None,
1713
+ label_color: ParsableManimColor | None = None,
1674
1714
  triangle_size: float = MED_SMALL_BUFF,
1675
- triangle_color: Color | None = WHITE,
1676
- line_func: Line = Line,
1677
- line_color: Color = YELLOW,
1715
+ triangle_color: ParsableManimColor | None = WHITE,
1716
+ line_func: type[Line] = Line,
1717
+ line_color: ParsableManimColor = YELLOW,
1678
1718
  ) -> VGroup:
1679
1719
  """Creates a labelled triangle marker with a vertical line from the x-axis
1680
1720
  to a curve at a given x-value.
@@ -1806,8 +1846,8 @@ class Axes(VGroup, CoordinateSystem, metaclass=ConvertToOpenGL):
1806
1846
  x_axis_config: dict | None = None,
1807
1847
  y_axis_config: dict | None = None,
1808
1848
  tips: bool = True,
1809
- **kwargs,
1810
- ):
1849
+ **kwargs: Any,
1850
+ ) -> None:
1811
1851
  VGroup.__init__(self, **kwargs)
1812
1852
  CoordinateSystem.__init__(self, x_range, y_range, x_length, y_length)
1813
1853
 
@@ -1874,7 +1914,7 @@ class Axes(VGroup, CoordinateSystem, metaclass=ConvertToOpenGL):
1874
1914
  @staticmethod
1875
1915
  def _update_default_configs(
1876
1916
  default_configs: tuple[dict[Any, Any]], passed_configs: tuple[dict[Any, Any]]
1877
- ):
1917
+ ) -> None:
1878
1918
  """Takes in two tuples of dicts and return modifies the first such that values from
1879
1919
  ``passed_configs`` overwrite values in ``default_configs``. If a key does not exist
1880
1920
  in default_configs, it is added to the dict.
@@ -1889,6 +1929,8 @@ class Axes(VGroup, CoordinateSystem, metaclass=ConvertToOpenGL):
1889
1929
  passed_configs
1890
1930
  The dict that will be used to update.
1891
1931
 
1932
+ Examples
1933
+ --------
1892
1934
  To create a tuple with one dictionary, add a comma after the element:
1893
1935
 
1894
1936
  .. code-block:: python
@@ -1907,7 +1949,7 @@ class Axes(VGroup, CoordinateSystem, metaclass=ConvertToOpenGL):
1907
1949
  def _create_axis(
1908
1950
  self,
1909
1951
  range_terms: Sequence[float],
1910
- axis_config: dict,
1952
+ axis_config: dict[str, Any],
1911
1953
  length: float,
1912
1954
  ) -> NumberLine:
1913
1955
  """Creates an axis and dynamically adjusts its position depending on where 0 is located on the line.
@@ -1995,40 +2037,47 @@ class Axes(VGroup, CoordinateSystem, metaclass=ConvertToOpenGL):
1995
2037
 
1996
2038
  self.add(plane, dot_scene, ax, dot_axes, lines)
1997
2039
  """
2040
+ coords = np.asarray(coords)
1998
2041
  origin = self.x_axis.number_to_point(
1999
2042
  self._origin_shift([self.x_axis.x_min, self.x_axis.x_max]),
2000
2043
  )
2001
2044
 
2002
- coords = np.asarray(coords)
2003
-
2004
- # if called like coords_to_point(1, 2, 3), then coords is a 1x3 array
2005
- transposed = False
2006
- if coords.ndim == 1:
2007
- # original implementation of coords_to_point for performance in the legacy case
2008
- result = np.array(origin)
2009
- for axis, number in zip(self.get_axes(), coords):
2010
- result += axis.number_to_point(number) - origin
2011
- return result
2012
- # if called like coords_to_point([1, 2, 3],[4, 5, 6]), then it shall be used as [1,4], [2,5], [3,6] and return the points as ([x_0,x_1],[y_0,y_1],[z_0,z_1])
2013
- elif coords.ndim == 2:
2014
- coords = coords.T
2015
- transposed = True
2016
- # if called like coords_to_point(np.array([[1, 2, 3],[4,5,6]])), reduce dimension by 1
2017
- elif coords.ndim == 3:
2018
- coords = np.squeeze(coords)
2019
- # else the coords is a Nx1, Nx2, Nx3 array so we do not need to modify the array
2020
-
2021
- points = origin + np.sum(
2022
- [
2023
- axis.number_to_point(number) - origin
2024
- for number, axis in zip(coords.T, self.get_axes())
2025
- ],
2026
- axis=0,
2027
- )
2028
- # if called with single coord, then return a point instead of a list of points
2029
- if transposed:
2030
- return points.T
2031
- return points
2045
+ # Is coords in the format ([[x1 y1 z1] [x2 y2 z2] ...])? (True)
2046
+ # Or is coords in the format (x, y, z) or ([x1 x2 ...], [y1 y2 ...], [z1 z2 ...])? (False)
2047
+ # The latter is preferred.
2048
+ are_coordinates_transposed = False
2049
+
2050
+ # If coords is in the format ([[x1 y1 z1] [x2 y2 z2] ...]):
2051
+ if coords.ndim == 3:
2052
+ # Extract from original tuple: now coords looks like [[x y z]] or [[x1 y1 z1] [x2 y2 z2] ...].
2053
+ coords = coords[0]
2054
+ # If there's a single coord (coords = [[x y z]]), extract it so that
2055
+ # coords = [x y z] and coords_to_point returns a single point.
2056
+ if coords.shape[0] == 1:
2057
+ coords = coords[0]
2058
+ # Else, if coords looks more like [[x1 y1 z1] [x2 y2 z2] ...], transform them (by
2059
+ # transposing) into the format [[x1 x2 ...] [y1 y2 ...] [z1 z2 ...]] for later processing.
2060
+ else:
2061
+ coords = coords.T
2062
+ are_coordinates_transposed = True
2063
+ # Otherwise, coords already looked like (x, y, z) or ([x1 x2 ...], [y1 y2 ...], [z1 z2 ...]),
2064
+ # so no further processing is needed.
2065
+
2066
+ # Now coords should either look like [x y z] or [[x1 x2 ...] [y1 y2 ...] [z1 z2 ...]],
2067
+ # so it can be iterated directly. Each element is either a float representing a single
2068
+ # coordinate, or a float ndarray of coordinates corresponding to a single axis.
2069
+ # Although "points" and "nums" are in plural, there might be a single point or number.
2070
+ points = self.x_axis.number_to_point(coords[0])
2071
+ other_axes = self.axes.submobjects[1:]
2072
+ for axis, nums in zip(other_axes, coords[1:]):
2073
+ points += axis.number_to_point(nums) - origin
2074
+
2075
+ # Return points as is, except if coords originally looked like
2076
+ # ([x1 x2 ...], [y1 y2 ...], [z1 z2 ...]), which is determined by the conditions below. In
2077
+ # that case, the current implementation requires that the results have to be transposed.
2078
+ if are_coordinates_transposed or points.ndim == 1:
2079
+ return points
2080
+ return points.T
2032
2081
 
2033
2082
  def point_to_coords(self, point: Sequence[float]) -> np.ndarray:
2034
2083
  """Accepts a point from the scene and returns its coordinates with respect to the axes.
@@ -2146,11 +2195,11 @@ class Axes(VGroup, CoordinateSystem, metaclass=ConvertToOpenGL):
2146
2195
  x_values: Iterable[float],
2147
2196
  y_values: Iterable[float],
2148
2197
  z_values: Iterable[float] | None = None,
2149
- line_color: Color = YELLOW,
2198
+ line_color: ParsableManimColor = YELLOW,
2150
2199
  add_vertex_dots: bool = True,
2151
2200
  vertex_dot_radius: float = DEFAULT_DOT_RADIUS,
2152
- vertex_dot_style: dict | None = None,
2153
- **kwargs,
2201
+ vertex_dot_style: dict[str, Any] | None = None,
2202
+ **kwargs: Any,
2154
2203
  ) -> VDict:
2155
2204
  """Draws a line graph.
2156
2205
 
@@ -2292,15 +2341,15 @@ class ThreeDAxes(Axes):
2292
2341
  x_length: float | None = config.frame_height + 2.5,
2293
2342
  y_length: float | None = config.frame_height + 2.5,
2294
2343
  z_length: float | None = config.frame_height - 1.5,
2295
- z_axis_config: dict | None = None,
2296
- z_normal: Sequence[float] = DOWN,
2344
+ z_axis_config: dict[str, Any] | None = None,
2345
+ z_normal: Vector3 = DOWN,
2297
2346
  num_axis_pieces: int = 20,
2298
2347
  light_source: Sequence[float] = 9 * DOWN + 7 * LEFT + 10 * OUT,
2299
2348
  # opengl stuff (?)
2300
2349
  depth=None,
2301
2350
  gloss=0.5,
2302
- **kwargs,
2303
- ):
2351
+ **kwargs: dict[str, Any],
2352
+ ) -> None:
2304
2353
  super().__init__(
2305
2354
  x_range=x_range,
2306
2355
  x_length=x_length,
@@ -2356,14 +2405,14 @@ class ThreeDAxes(Axes):
2356
2405
  self._add_3d_pieces()
2357
2406
  self._set_axis_shading()
2358
2407
 
2359
- def _add_3d_pieces(self):
2408
+ def _add_3d_pieces(self) -> None:
2360
2409
  for axis in self.axes:
2361
2410
  axis.pieces = VGroup(*axis.get_pieces(self.num_axis_pieces))
2362
2411
  axis.add(axis.pieces)
2363
2412
  axis.set_stroke(width=0, family=False)
2364
2413
  axis.set_shade_in_3d(True)
2365
2414
 
2366
- def _set_axis_shading(self):
2415
+ def _set_axis_shading(self) -> None:
2367
2416
  def make_func(axis):
2368
2417
  vect = self.light_source
2369
2418
  return lambda: (
@@ -2383,8 +2432,8 @@ class ThreeDAxes(Axes):
2383
2432
  edge: Sequence[float] = UR,
2384
2433
  direction: Sequence[float] = UR,
2385
2434
  buff: float = SMALL_BUFF,
2386
- rotation=PI / 2,
2387
- rotation_axis=OUT,
2435
+ rotation: float = PI / 2,
2436
+ rotation_axis: Vector3 = OUT,
2388
2437
  **kwargs,
2389
2438
  ) -> Mobject:
2390
2439
  """Generate a y-axis label.
@@ -2431,12 +2480,12 @@ class ThreeDAxes(Axes):
2431
2480
  def get_z_axis_label(
2432
2481
  self,
2433
2482
  label: float | str | Mobject,
2434
- edge: Sequence[float] = OUT,
2435
- direction: Sequence[float] = RIGHT,
2483
+ edge: Vector3 = OUT,
2484
+ direction: Vector3 = RIGHT,
2436
2485
  buff: float = SMALL_BUFF,
2437
- rotation=PI / 2,
2438
- rotation_axis=RIGHT,
2439
- **kwargs,
2486
+ rotation: float = PI / 2,
2487
+ rotation_axis: Vector3 = RIGHT,
2488
+ **kwargs: Any,
2440
2489
  ) -> Mobject:
2441
2490
  """Generate a z-axis label.
2442
2491
 
@@ -2618,11 +2667,11 @@ class NumberPlane(Axes):
2618
2667
  ),
2619
2668
  x_length: float | None = None,
2620
2669
  y_length: float | None = None,
2621
- background_line_style: dict | None = None,
2622
- faded_line_style: dict | None = None,
2670
+ background_line_style: dict[str, Any] | None = None,
2671
+ faded_line_style: dict[str, Any] | None = None,
2623
2672
  faded_line_ratio: int = 1,
2624
2673
  make_smooth_after_applying_functions: bool = True,
2625
- **kwargs,
2674
+ **kwargs: dict[str, Any],
2626
2675
  ):
2627
2676
  # configs
2628
2677
  self.axis_config = {
@@ -2667,7 +2716,7 @@ class NumberPlane(Axes):
2667
2716
 
2668
2717
  self._init_background_lines()
2669
2718
 
2670
- def _init_background_lines(self):
2719
+ def _init_background_lines(self) -> None:
2671
2720
  """Will init all the lines of NumberPlanes (faded or not)"""
2672
2721
  if self.faded_line_style is None:
2673
2722
  style = dict(self.background_line_style)
@@ -2788,13 +2837,13 @@ class NumberPlane(Axes):
2788
2837
  lines2.add(new_line)
2789
2838
  return lines1, lines2
2790
2839
 
2791
- def get_vector(self, coords: Sequence[float], **kwargs):
2840
+ def get_vector(self, coords: Sequence[ManimFloat], **kwargs: Any) -> Arrow:
2792
2841
  kwargs["buff"] = 0
2793
2842
  return Arrow(
2794
2843
  self.coords_to_point(0, 0), self.coords_to_point(*coords), **kwargs
2795
2844
  )
2796
2845
 
2797
- def prepare_for_nonlinear_transform(self, num_inserted_curves: int = 50):
2846
+ def prepare_for_nonlinear_transform(self, num_inserted_curves: int = 50) -> Self:
2798
2847
  for mob in self.family_members_with_points():
2799
2848
  num_curves = mob.get_num_curves()
2800
2849
  if num_inserted_curves > num_curves:
@@ -2888,13 +2937,13 @@ class PolarPlane(Axes):
2888
2937
  azimuth_direction: str = "CCW",
2889
2938
  azimuth_label_buff: float = SMALL_BUFF,
2890
2939
  azimuth_label_font_size: float = 24,
2891
- radius_config: dict | None = None,
2892
- background_line_style: dict | None = None,
2893
- faded_line_style: dict | None = None,
2940
+ radius_config: dict[str, Any] | None = None,
2941
+ background_line_style: dict[str, Any] | None = None,
2942
+ faded_line_style: dict[str, Any] | None = None,
2894
2943
  faded_line_ratio: int = 1,
2895
2944
  make_smooth_after_applying_functions: bool = True,
2896
- **kwargs,
2897
- ):
2945
+ **kwargs: Any,
2946
+ ) -> None:
2898
2947
  # error catching
2899
2948
  if azimuth_units in ["PI radians", "TAU radians", "degrees", "gradians", None]:
2900
2949
  self.azimuth_units = azimuth_units
@@ -2965,7 +3014,7 @@ class PolarPlane(Axes):
2965
3014
 
2966
3015
  self._init_background_lines()
2967
3016
 
2968
- def _init_background_lines(self):
3017
+ def _init_background_lines(self) -> None:
2969
3018
  """Will init all the lines of NumberPlanes (faded or not)"""
2970
3019
  if self.faded_line_style is None:
2971
3020
  style = dict(self.background_line_style)
@@ -3045,13 +3094,13 @@ class PolarPlane(Axes):
3045
3094
  """
3046
3095
  return self.axes
3047
3096
 
3048
- def get_vector(self, coords, **kwargs):
3097
+ def get_vector(self, coords: Sequence[ManimFloat], **kwargs: Any) -> Arrow:
3049
3098
  kwargs["buff"] = 0
3050
3099
  return Arrow(
3051
3100
  self.coords_to_point(0, 0), self.coords_to_point(*coords), **kwargs
3052
3101
  )
3053
3102
 
3054
- def prepare_for_nonlinear_transform(self, num_inserted_curves=50):
3103
+ def prepare_for_nonlinear_transform(self, num_inserted_curves: int = 50) -> Self:
3055
3104
  for mob in self.family_members_with_points():
3056
3105
  num_curves = mob.get_num_curves()
3057
3106
  if num_inserted_curves > num_curves:
@@ -3062,7 +3111,7 @@ class PolarPlane(Axes):
3062
3111
  self,
3063
3112
  r_values: Iterable[float] | None = None,
3064
3113
  a_values: Iterable[float] | None = None,
3065
- **kwargs,
3114
+ **kwargs: Any,
3066
3115
  ) -> VDict:
3067
3116
  """Gets labels for the coordinates
3068
3117
 
@@ -3164,7 +3213,7 @@ class PolarPlane(Axes):
3164
3213
  self,
3165
3214
  r_values: Iterable[float] | None = None,
3166
3215
  a_values: Iterable[float] | None = None,
3167
- ):
3216
+ ) -> Self:
3168
3217
  """Adds the coordinates.
3169
3218
 
3170
3219
  Parameters
@@ -3177,7 +3226,7 @@ class PolarPlane(Axes):
3177
3226
  self.add(self.get_coordinate_labels(r_values, a_values))
3178
3227
  return self
3179
3228
 
3180
- def get_radian_label(self, number, font_size=24, **kwargs):
3229
+ def get_radian_label(self, number, font_size: float = 24, **kwargs: Any) -> MathTex:
3181
3230
  constant_label = {"PI radians": r"\pi", "TAU radians": r"\tau"}[
3182
3231
  self.azimuth_units
3183
3232
  ]
@@ -3246,7 +3295,7 @@ class ComplexPlane(NumberPlane):
3246
3295
 
3247
3296
  """
3248
3297
 
3249
- def __init__(self, **kwargs):
3298
+ def __init__(self, **kwargs: Any) -> None:
3250
3299
  super().__init__(
3251
3300
  **kwargs,
3252
3301
  )
@@ -3272,7 +3321,7 @@ class ComplexPlane(NumberPlane):
3272
3321
  """Abbreviation for :meth:`number_to_point`."""
3273
3322
  return self.number_to_point(number)
3274
3323
 
3275
- def point_to_number(self, point: Sequence[float]) -> complex:
3324
+ def point_to_number(self, point: Point3D) -> complex:
3276
3325
  """Accepts a point and returns a complex number equivalent to that point on the plane.
3277
3326
 
3278
3327
  Parameters
@@ -3289,7 +3338,7 @@ class ComplexPlane(NumberPlane):
3289
3338
  x, y = self.point_to_coords(point)
3290
3339
  return complex(x, y)
3291
3340
 
3292
- def p2n(self, point: Sequence[float]) -> complex:
3341
+ def p2n(self, point: Point3D) -> complex:
3293
3342
  """Abbreviation for :meth:`point_to_number`."""
3294
3343
  return self.point_to_number(point)
3295
3344
 
@@ -3307,7 +3356,7 @@ class ComplexPlane(NumberPlane):
3307
3356
  return [*x_numbers, *y_numbers]
3308
3357
 
3309
3358
  def get_coordinate_labels(
3310
- self, *numbers: Iterable[float | complex], **kwargs
3359
+ self, *numbers: Iterable[float | complex], **kwargs: Any
3311
3360
  ) -> VGroup:
3312
3361
  """Generates the :class:`~.DecimalNumber` mobjects for the coordinates of the plane.
3313
3362
 
@@ -3342,7 +3391,9 @@ class ComplexPlane(NumberPlane):
3342
3391
  self.coordinate_labels.add(number_mob)
3343
3392
  return self.coordinate_labels
3344
3393
 
3345
- def add_coordinates(self, *numbers: Iterable[float | complex], **kwargs):
3394
+ def add_coordinates(
3395
+ self, *numbers: Iterable[float | complex], **kwargs: Any
3396
+ ) -> Self:
3346
3397
  """Adds the labels produced from :meth:`~.NumberPlane.get_coordinate_labels` to the plane.
3347
3398
 
3348
3399
  Parameters