Animation engine for explanatory math videos
This report summarizes scanner evidence for 3b1b/manim, a Python project with 94,859 GitHub stars. SynthScan examined 29,937 lines of code across 131 source files, recording 440 pattern matches distributed across 13 syntactic categories. The legacy adjusted pattern signal is 15.3 (Elevated pattern signal); it is not an authorship estimate.
Use the findings to ask whether maintainers can explain intent, verify dependencies, simplify unnecessary scaffolding, and focus review effort. Risk Payload v1 adds ownership, supply-chain, over-engineering, and review-effort vectors when available. These are prompts for human verification, not probabilities, security findings, or measured maintenance costs.
Use each vector to guide manual verification of the underlying findings.
Can maintainers explain intent, assumptions, and trade-offs? 208 finding(s).
Are imports declared and package/API names verified? 203 finding(s).
Are wrappers, guards, and repeated structures necessary? 203 finding(s).
Which changes need focused human review? 440 finding(s).
This chart tracks the legacy adjusted pattern score across scan runs. Changes can reflect source changes, scan coverage, or detector/scoring versions; they do not measure AI adoption or prove that a team refactored code. Compare runs only when their scoring versions are compatible. The dashed line tracks the raw pattern-hit count.
Groups findings by configured severity weight. Severity is not a confidence estimate, security rating, or proof that a package is missing. Verify imports against the project's manifests and inspect each finding in its local design context.
This horizontal bar chart shows where configured pattern scores accumulate across directories. Treat the bars as locations to inspect, not as evidence of authorship or code quality. Use the file-level findings to decide whether a directory needs a focused ownership, dependency, complexity, or review check.
The scanner identified 440 distinct pattern matches across 13 syntactic categories. Each entry below represents a discrete location in the source code where the engine recorded a detector match to inspect in context. Expand any category row to inspect the individual file paths, line numbers, code snippets, and the lexical context (CODE, COMMENT, or STRING) in which each match was detected.
Reading the findings table: The Severity column indicates the configured finding weight (CRITICAL / HIGH / MEDIUM / LOW). The Context column identifies whether the match occurred inside executable code, an inline comment, or a string literal — legacy comment-context matches receive a ×1.5 score weight. The ⚡ bolt icon marks clustered matches: three or more patterns within a 10-line window, each receiving an additional ×1.5 density multiplier under the legacy scoring model.
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | example_scenes.py | 1 | CODE | |
| LOW | manimlib/config.py | 1 | CODE | |
| LOW | manimlib/window.py | 1 | CODE | |
| LOW | manimlib/event_keys.py | 14 | CODE | |
| LOW | manimlib/constants.py | 1 | CODE | |
| LOW | manimlib/__init__.py | 12 | CODE | |
| LOW | manimlib/__init__.py | 19 | CODE | |
| LOW | manimlib/__init__.py | 21 | CODE | |
| LOW | manimlib/__init__.py | 23 | CODE | |
| LOW | manimlib/__init__.py | 24 | CODE | |
| LOW | manimlib/__init__.py | 25 | CODE | |
| LOW | manimlib/__init__.py | 26 | CODE | |
| LOW | manimlib/__init__.py | 27 | CODE | |
| LOW | manimlib/__init__.py | 28 | CODE | |
| LOW | manimlib/__init__.py | 29 | CODE | |
| LOW | manimlib/__init__.py | 30 | CODE | |
| LOW | manimlib/__init__.py | 31 | CODE | |
| LOW | manimlib/__init__.py | 32 | CODE | |
| LOW | manimlib/__init__.py | 33 | CODE | |
| LOW | manimlib/__init__.py | 34 | CODE | |
| LOW | manimlib/__init__.py | 35 | CODE | |
| LOW | manimlib/__init__.py | 37 | CODE | |
| LOW | manimlib/__init__.py | 39 | CODE | |
| LOW | manimlib/__init__.py | 40 | CODE | |
| LOW | manimlib/__init__.py | 41 | CODE | |
| LOW | manimlib/__init__.py | 42 | CODE | |
| LOW | manimlib/__init__.py | 43 | CODE | |
| LOW | manimlib/__init__.py | 44 | CODE | |
| LOW | manimlib/__init__.py | 45 | CODE | |
| LOW | manimlib/__init__.py | 46 | CODE | |
| LOW | manimlib/__init__.py | 47 | CODE | |
| LOW | manimlib/__init__.py | 48 | CODE | |
| LOW | manimlib/__init__.py | 49 | CODE | |
| LOW | manimlib/__init__.py | 50 | CODE | |
| LOW | manimlib/__init__.py | 51 | CODE | |
| LOW | manimlib/__init__.py | 52 | CODE | |
| LOW | manimlib/__init__.py | 53 | CODE | |
| LOW | manimlib/__init__.py | 54 | CODE | |
| LOW | manimlib/__init__.py | 55 | CODE | |
| LOW | manimlib/__init__.py | 56 | CODE | |
| LOW | manimlib/__init__.py | 57 | CODE | |
| LOW | manimlib/__init__.py | 58 | CODE | |
| LOW | manimlib/__init__.py | 59 | CODE | |
| LOW | manimlib/__init__.py | 60 | CODE | |
| LOW | manimlib/__init__.py | 61 | CODE | |
| LOW | manimlib/__init__.py | 62 | CODE | |
| LOW | manimlib/__init__.py | 63 | CODE | |
| LOW | manimlib/__init__.py | 64 | CODE | |
| LOW | manimlib/__init__.py | 65 | CODE | |
| LOW | manimlib/__init__.py | 66 | CODE | |
| LOW | manimlib/__init__.py | 67 | CODE | |
| LOW | manimlib/__init__.py | 68 | CODE | |
| LOW | manimlib/__init__.py | 69 | CODE | |
| LOW | manimlib/__init__.py | 71 | CODE | |
| LOW | manimlib/__init__.py | 72 | CODE | |
| LOW | manimlib/__init__.py | 74 | CODE | |
| LOW | manimlib/__init__.py | 75 | CODE | |
| LOW | manimlib/__init__.py | 77 | CODE | |
| LOW | manimlib/__init__.py | 78 | CODE | |
| LOW | manimlib/__init__.py | 79 | CODE | |
| 143 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | manimlib/config.py | 268 | def update_file_writer_config(config: Dict, args: Namespace): | CODE |
| LOW | manimlib/window.py | 293 | def pixel_coords_to_space_coords( | CODE |
| LOW | manimlib/extract_scene.py | 146 | def insert_embed_line_to_module(module: Module, run_config: Dict) -> None: | CODE |
| LOW | manimlib/module_loader.py | 53 | def _exec_module_and_track_imports(spec, module: Module) -> set[str]: | CODE |
| LOW | manimlib/camera/camera_frame.py | 107 | def get_inverse_camera_rotation_matrix(self): | CODE |
| LOW | manimlib/camera/camera_frame.py | 255 | def get_implied_camera_location(self) -> np.ndarray: | CODE |
| LOW | manimlib/animation/transform_matching_parts.py | 101 | def find_pairs_with_matching_shapes( | CODE |
| LOW | manimlib/animation/animation.py | 130 | def update_reference_mobjects(self, dt: float, frame_rate: float | None = None) -> None: | CODE |
| LOW | manimlib/animation/transform.py | 75 | def check_target_mobject_validity(self) -> None: | CODE |
| LOW⚡ | manimlib/animation/composition.py | 85 | def update_reference_mobjects(self, dt: float, frame_rate: float | None = None) -> None: | CODE |
| LOW⚡ | manimlib/animation/composition.py | 89 | def build_animations_with_timings(self, lag_ratio: float) -> None: | CODE |
| LOW | manimlib/animation/composition.py | 140 | def update_reference_mobjects(self, dt: float, frame_rate: float | None = None) -> None: | CODE |
| LOW | manimlib/utils/rate_functions.py | 48 | def there_and_back_with_pause(t: float, pause_ratio: float = 1. / 3) -> float: | CODE |
| LOW | manimlib/utils/bezier.py | 75 | def partial_quadratic_bezier_points( | CODE |
| LOW | manimlib/utils/bezier.py | 117 | def set_array_by_interpolation( | CODE |
| LOW | manimlib/utils/bezier.py | 174 | def quadratic_bezier_points_for_arc(angle: float, n_components: int = 8): | CODE |
| LOW | manimlib/utils/bezier.py | 184 | def approx_smooth_quadratic_bezier_handles( | CODE |
| LOW | manimlib/utils/bezier.py | 257 | def get_smooth_cubic_bezier_handle_points( | CODE |
| LOW | manimlib/utils/bezier.py | 343 | def get_quadratic_approximation_of_cubic( | CODE |
| LOW | manimlib/utils/bezier.py | 415 | def get_smooth_quadratic_bezier_path_through( | CODE |
| LOW | manimlib/utils/structured_array.py | 190 | def turn_off_interpolation_skip(self) -> None: | CODE |
| LOW | manimlib/utils/space_ops.py | 93 | def quaternion_from_angle_axis( | CODE |
| LOW | manimlib/utils/space_ops.py | 100 | def angle_axis_from_quaternion(quat: Vect4) -> Tuple[float, Vect3]: | CODE |
| LOW | manimlib/utils/space_ops.py | 136 | def rotation_matrix_transpose_from_quaternion(quat: Vect4) -> Matrix3x3: | CODE |
| LOW | manimlib/utils/space_ops.py | 140 | def rotation_matrix_from_quaternion(quat: Vect4) -> Matrix3x3: | CODE |
| LOW | manimlib/utils/space_ops.py | 151 | def rotation_matrix_transpose(angle: float, axis: Vect3) -> Matrix3x3: | CODE |
| LOW | manimlib/utils/space_ops.py | 360 | def get_closest_point_on_line(a: VectN, b: VectN, p: VectN) -> VectN: | CODE |
| LOW | manimlib/utils/images.py | 17 | def get_full_raster_image_path(image_file_name: str) -> str: | CODE |
| LOW | manimlib/utils/images.py | 33 | def get_full_vector_image_path(image_file_name: str) -> str: | CODE |
| LOW | manimlib/utils/images.py | 41 | def get_full_three_d_model_path(model_file_name: str) -> str: | CODE |
| LOW | manimlib/utils/family_ops.py | 11 | def extract_mobject_family_members( | CODE |
| LOW | manimlib/utils/iterables.py | 129 | def resize_with_interpolation(nparray: np.ndarray, length: int) -> np.ndarray: | CODE |
| LOW | manimlib/scene/scene_file_writer.py | 99 | def init_partial_movie_directory(self): | CODE |
| LOW | manimlib/scene/scene_file_writer.py | 126 | def get_next_partial_movie_path(self) -> str: | CODE |
| LOW | manimlib/scene/scene_file_writer.py | 283 | def set_progress_display_description(self, file: str = "", sub_desc: str = "") -> None: | CODE |
| LOW | manimlib/scene/scene.py | 303 | def get_mobject_family_members(self) -> list[Mobject]: | CODE |
| LOW | manimlib/scene/scene.py | 481 | def get_animation_time_progression( | CODE |
| LOW | manimlib/scene/scene.py | 493 | def get_wait_time_progression( | CODE |
| LOW | manimlib/scene/scene.py | 547 | def progress_through_animations(self, animations: Iterable[Animation]) -> None: | CODE |
| LOW | manimlib/scene/scene.py | 638 | def revert_to_original_skipping_status(self): | CODE |
| LOW | manimlib/scene/interactive_scene.py | 139 | def update_selection_rectangle(self, rect: Rectangle): | CODE |
| LOW | manimlib/scene/interactive_scene.py | 155 | def update_selection_highlight(self, highlight: Mobject): | CODE |
| LOW | manimlib/scene/interactive_scene.py | 257 | def regenerate_selection_search_set(self): | CODE |
| LOW | manimlib/scene/interactive_scene.py | 585 | def handle_sweeping_selection(self, point: Vect3): | CODE |
| LOW | manimlib/scene/scene_embed.py | 40 | def get_ipython_shell_for_embedded_scene(self) -> InteractiveShellEmbed: | CODE |
| LOW | manimlib/scene/scene_embed.py | 102 | def ensure_frame_update_post_cell(self): | CODE |
| LOW | manimlib/mobject/matrix.py | 157 | def add_background_to_entries(self) -> Self: | CODE |
| LOW | manimlib/mobject/matrix.py | 170 | def swap_entries_for_ellipses( | CODE |
| LOW | manimlib/mobject/vector_field.py | 34 | def get_vectorized_rgb_gradient_function( | CODE |
| LOW | manimlib/mobject/vector_field.py | 57 | def get_rgb_gradient_function( | CODE |
| LOW | manimlib/mobject/vector_field.py | 89 | def move_submobjects_along_vector_field( | CODE |
| LOW | manimlib/mobject/vector_field.py | 103 | def move_points_along_vector_field( | CODE |
| LOW | manimlib/mobject/vector_field.py | 230 | def init_base_stroke_width_array(self, n_sample_points): | CODE |
| LOW | manimlib/mobject/boolean_ops.py | 12 | def _convert_vmobject_to_skia_path(vmobject: VMobject) -> pathops.Path: | CODE |
| LOW | manimlib/mobject/boolean_ops.py | 26 | def _convert_skia_path_to_vmobject( | CODE |
| LOW⚡ | manimlib/mobject/numbers.py | 81 | def set_submobjects_from_number(self, number: float | complex) -> None: | CODE |
| LOW | manimlib/mobject/numbers.py | 220 | def _handle_scale_side_effects(self, scale_factor: float) -> Self: | CODE |
| LOW | manimlib/mobject/interactive.py | 521 | def move_panel_and_controls_to_panel_opener(self) -> None: | CODE |
| LOW | manimlib/mobject/interactive.py | 559 | def panel_opener_on_mouse_drag(self, mob, event_data: dict[str, np.ndarray]) -> bool: | CODE |
| LOW | manimlib/mobject/geometry.py | 116 | def reset_endpoints_based_on_tip(self, tip: ArrowTip, at_start: bool) -> Self: | CODE |
| 80 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | manimlib/camera/camera.py | 109 | CODE | |
| LOW | manimlib/animation/animation.py | 24 | CODE | |
| LOW | manimlib/animation/specialized.py | 17 | CODE | |
| LOW | manimlib/utils/color.py | 163 | CODE | |
| LOW | manimlib/scene/scene_file_writer.py | 29 | CODE | |
| LOW | manimlib/scene/scene.py | 64 | CODE | |
| LOW | manimlib/mobject/matrix.py | 25 | CODE | |
| LOW | manimlib/mobject/vector_field.py | 52 | CODE | |
| LOW | manimlib/mobject/vector_field.py | 142 | CODE | |
| LOW | manimlib/mobject/vector_field.py | 337 | CODE | |
| LOW | manimlib/mobject/numbers.py | 35 | CODE | |
| LOW | manimlib/mobject/fractals.py | 211 | CODE | |
| LOW | manimlib/mobject/interactive.py | 384 | CODE | |
| LOW | manimlib/mobject/geometry.py | 539 | CODE | |
| LOW | manimlib/mobject/geometry.py | 1076 | CODE | |
| LOW | manimlib/mobject/number_line.py | 28 | CODE | |
| LOW | manimlib/mobject/number_line.py | 247 | CODE | |
| LOW | manimlib/mobject/probability.py | 197 | CODE | |
| LOW | manimlib/mobject/coordinate_systems.py | 363 | CODE | |
| LOW | manimlib/mobject/coordinate_systems.py | 446 | CODE | |
| LOW | manimlib/mobject/mobject.py | 98 | CODE | |
| LOW | manimlib/mobject/mobject.py | 519 | CODE | |
| LOW | manimlib/mobject/svg/drawings.py | 189 | CODE | |
| LOW | manimlib/mobject/svg/drawings.py | 358 | CODE | |
| LOW | manimlib/mobject/svg/drawings.py | 594 | CODE | |
| LOW | manimlib/mobject/svg/drawings.py | 688 | CODE | |
| LOW | manimlib/mobject/svg/svg_mobject.py | 62 | CODE | |
| LOW | manimlib/mobject/svg/string_mobject.py | 46 | CODE | |
| LOW | manimlib/mobject/svg/text_mobject.py | 136 | CODE | |
| LOW | manimlib/mobject/svg/old_tex_mobject.py | 23 | CODE | |
| LOW | manimlib/mobject/svg/tex_mobject.py | 38 | CODE | |
| LOW | manimlib/mobject/types/vectorized_mobject.py | 94 | CODE | |
| LOW | manimlib/mobject/types/vectorized_mobject.py | 364 | CODE | |
| LOW | manimlib/mobject/types/surface.py | 60 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | manimlib/__main__.py | 41 | except KillEmbedded: | CODE |
| HIGH | manimlib/event_handler/event_dispatcher.py | 32 | except: | CODE |
| HIGH | manimlib/event_handler/event_listner.py | 29 | except: | CODE |
| HIGH | manimlib/scene/scene.py | 159 | except EndScene: | CODE |
| HIGH | manimlib/scene/interactive_scene.py | 173 | except ValueError: | CODE |
| HIGH | manimlib/scene/interactive_scene.py | 382 | except ValueError: | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | manimlib/logger.py | 5 | __all__ = ["log"] | CODE |
| LOW | manimlib/renderer/__init__.py | 4 | __all__ = ["Gpu", "Renderer"] | CODE |
| LOW | manimlib/renderer/texture.py | 83 | def set_layers(self, layers: np.ndarray) -> None: | CODE |
| LOW | manimlib/animation/creation.py | 206 | def update_submobject_list(self, index: int) -> None: | CODE |
| LOW | manimlib/animation/creation.py | 219 | def update_submobject_list(self, index: int) -> None: | CODE |
| LOW | manimlib/animation/animation.py | 130 | def update_reference_mobjects(self, dt: float, frame_rate: float | None = None) -> None: | CODE |
| LOW | manimlib/animation/transform.py | 87 | def update_config(self, **kwargs) -> None: | CODE |
| LOW⚡ | manimlib/animation/composition.py | 85 | def update_reference_mobjects(self, dt: float, frame_rate: float | None = None) -> None: | CODE |
| LOW | manimlib/animation/composition.py | 140 | def update_reference_mobjects(self, dt: float, frame_rate: float | None = None) -> None: | CODE |
| LOW | manimlib/utils/structured_array.py | 82 | def set_array(self, array: np.ndarray) -> None: | CODE |
| LOW | manimlib/scene/scene_file_writer.py | 283 | def set_progress_display_description(self, file: str = "", sub_desc: str = "") -> None: | CODE |
| LOW | manimlib/scene/scene.py | 236 | def update_frame(self, dt: float = 0, force_draw: bool = False) -> None: | CODE |
| LOW | manimlib/scene/scene.py | 267 | def update_mobjects(self, dt: float) -> None: | CODE |
| LOW | manimlib/scene/scene.py | 435 | def update_skipping_status(self) -> None: | CODE |
| LOW | manimlib/scene/scene.py | 875 | def set_background_color(self, background_color, background_opacity=1) -> None: | CODE |
| LOW⚡ | manimlib/mobject/numbers.py | 81 | def set_submobjects_from_number(self, number: float | complex) -> None: | CODE |
| LOW | manimlib/mobject/interactive.py | 125 | def set_value_anim(self, value: bool) -> None: | CODE |
| LOW | manimlib/mobject/interactive.py | 177 | def set_value_anim(self, value: bool) -> None: | CODE |
| LOW | manimlib/mobject/interactive.py | 258 | def set_value_anim(self, value: float) -> None: | CODE |
| LOW | manimlib/mobject/interactive.py | 420 | def set_value_anim(self, value: str) -> None: | CODE |
| LOW | manimlib/mobject/interactive.py | 423 | def update_text(self, value: str) -> None: | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | manimlib/module_loader.py | 139 | CODE | |
| LOW | manimlib/event_handler/event_dispatcher.py | 37 | CODE | |
| LOW | manimlib/scene/scene_file_writer.py | 363 | CODE | |
| LOW | manimlib/scene/scene.py | 826 | CODE | |
| LOW | manimlib/scene/scene.py | 934 | CODE | |
| LOW | manimlib/scene/interactive_scene.py | 407 | CODE | |
| LOW | manimlib/scene/interactive_scene.py | 481 | CODE | |
| LOW | manimlib/scene/interactive_scene.py | 554 | CODE | |
| LOW | manimlib/mobject/boolean_ops.py | 26 | CODE | |
| LOW | manimlib/mobject/interactive.py | 446 | CODE | |
| LOW | manimlib/mobject/coordinate_systems.py | 363 | CODE | |
| LOW | manimlib/mobject/mobject.py | 1353 | CODE | |
| LOW | manimlib/mobject/svg/svg_mobject.py | 227 | CODE | |
| LOW | manimlib/mobject/svg/text_mobject.py | 319 | CODE | |
| LOW | manimlib/mobject/svg/old_tex_mobject.py | 153 | CODE | |
| LOW | manimlib/mobject/svg/tex_mobject.py | 92 | CODE | |
| LOW | manimlib/mobject/types/vectorized_mobject.py | 326 | CODE | |
| LOW | manimlib/mobject/types/vectorized_mobject.py | 859 | CODE | |
| LOW | tests/render_compare.py | 208 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | manimlib/__main__.py | 24 | # Create a new dict to be able to upate without | COMMENT |
| MEDIUM | manimlib/__main__.py | 30 | # Create a reusable window | COMMENT |
| MEDIUM | manimlib/animation/indication.py | 235 | # Create a gaussian such that 3 sigmas out on either side | COMMENT |
| MEDIUM | manimlib/utils/tex_file_writing.py | 103 | temp_dir.mkdir(exist_ok=True) # Create the directory if it does not already exist | CODE |
| MEDIUM⚡ | manimlib/mobject/numbers.py | 82 | # Create the submobject list | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | manimlib/default_config.yml | 12 | # Set this to true if you want the path to video files | COMMENT |
| LOW | manimlib/utils/file_ops.py | 31 | # Check if this is a file online first, and if so, download | COMMENT |
| LOW | manimlib/utils/file_ops.py | 44 | # Check if what was passed in is already a valid path to a file | COMMENT |
| LOW | manimlib/mobject/mobject.py | 901 | # Check if mark as static or not for camera | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | manimlib/utils/tex_file_writing.py | 63 | Convert LaTeX string to SVG string. Args: latex: LaTeX source code template: Path to a template LaT | STRING |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | example_scenes.py | 300 | # If the argument itself might change, you can use f_always, | STRING |
| MEDIUM | manimlib/mobject/svg/old_tex_mobject.py | 111 | # tex == "\\frac", # you can use \\over as a alternative | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | manimlib/config.py | 260 | except Exception as err: | CODE |
| LOW | manimlib/scene/scene_embed.py | 142 | except Exception as e: | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | manimlib/default_config.yml | 1 | # This file determines the default configuration for how manim is | COMMENT |
| LOW | manimlib/default_config.yml | 41 | window: | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | manimlib/mobject/mobject.py | 1781 | # If empty, simply add n point mobjects | COMMENT |