Flake8 Changes + Fixing Warnings (#1968)

* Warning Removal

* Flake Stuff

* HotFix

* Docs Fix

* I'm Dumb

* Docs Fix 2

* Fixing Github Requests

* Fix

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* quick fix

* Add Deprecation Warning

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Weird Pre Commit Stuff

* Quick Fix

* Quick Fix

* Fix

* Flake Fix

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
GameDungeon 2021-09-03 12:45:48 -05:00 committed by GitHub
commit 94821c10d8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
217 changed files with 2246 additions and 1435 deletions

View file

@ -1,4 +1,4 @@
[codespell]
exclude-file=.codespell_ignorelines
check-hidden=True
ignore-words-list = sherif,
ignore-words-list = sherif

29
.flake8
View file

@ -1,20 +1,35 @@
[flake8]
# Exclude the grpc generated code
exclude = ./.*,manim/grpc/gen/*
max-complexity = 35
max-line-length = 211
max-complexity = 15
max-line-length = 88
statistics = True
# Prevents some flake8-rst-docstrings errors
rst-roles = attr,class,func,meth,mod,obj,ref,doc,exc
rst-directives = manim, SEEALSO, seealso
# Adds some more bugbear checks
select = B9
# Black Compatibility
extend-ignore = E203, W503,
# Unused imports, wildcard imports, and unused variables
F401, F403, F405, F841,
F401, F403, F405, F841, E501,
# Plug-in: flake8-builtins
A001, A002, A003,
# Plug-in: flake8-bugbear
B006, B007, B008, B009, B010, B011, B015,
B006, B008, B009, B010,
# Plug-in: flake8-simplify
SIM105, SIM106, SIM119,
# Plug-in: flake8-comprehensions
C408,
# Plug-in: flake8-pytest-style
PT001, PT004, PT006, PT011, PT018, PT022, PT023,
# Plug-in: flake8-docstrings
D100, D101, D102, D103, D104, D105, D106, D107,
@ -23,5 +38,7 @@ extend-ignore = E203, W503,
D400, D401, D402, D403, D412, D414,
# Plug-in: flake8-rst-docstrings
RST201, RST203, RST205, RST210, RST212, RST213, RST215,
RST301, RST303, RST304,
RST201, RST203, RST210, RST212, RST213, RST215,
RST301,
# I believe B009, B010, and F841 can be removed but I don't want to break things

1
.gitattributes vendored
View file

@ -8,4 +8,3 @@
*.wav binary
manim/grpc/gen/** linguist-generated=true

View file

@ -10,7 +10,7 @@
<!-- Optional for bugfixes, small enhancements, and documentation-related PRs. Otherwise, please give a short reasoning for your changes. -->
## Links to added or changed documentation pages
<!-- Please add links to the affected documentation pages (edit the description after opening the PR). The link to the documentation for your PR is https://manimce--####.org.readthedocs.build/en/####/, where #### represents the PR number. -->
<!-- Please add links to the affected documentation pages (edit the description after opening the PR). The link to the documentation for your PR is https://manimce--####.org.readthedocs.build/en/####/, where #### represents the PR number. -->
## Further Information and Comments

View file

@ -5,7 +5,7 @@ Before filling in the details, ensure:
- Added gradient support and documentation for SVG files
-->
## Changelog
## Changelog
<!-- Optional: more descriptive changelog entry than just the title for the upcoming
release. Write RST between the following start and end comments.-->
<!--changelog-start-->

View file

@ -6,7 +6,7 @@ Before filling in the details, ensure:
-->
## Summary of Changes
## Changelog
## Changelog
<!-- Optional: more descriptive changelog entry than just the title for the upcoming
release. Write RST between the following start and end comments.-->
<!--changelog-start-->

View file

@ -4,16 +4,13 @@ repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.0.1
hooks:
- id: check-ast
name: Validate Python
- id: trailing-whitespace
- id: mixed-line-ending
- repo: https://github.com/psf/black
rev: 21.8b0
hooks:
- id: black
- repo: https://github.com/asottile/blacken-docs
rev: v1.11.0
hooks:
- id: blacken-docs
additional_dependencies: [black==20.8b1]
- id: end-of-file-fixer
- id: check-toml
name: Validate Poetry
- repo: https://github.com/pycqa/isort
rev: 5.9.3
hooks:
@ -25,11 +22,44 @@ repos:
- id: isort
name: isort (pyi)
types: [pyi]
- repo: https://github.com/asottile/add-trailing-comma
rev: v2.1.0
hooks:
- id: add-trailing-comma
- repo: https://github.com/asottile/pyupgrade
rev: v2.25.0
hooks:
- id: pyupgrade
name: Update code to new python versions
args: [--py37-plus]
exclude: ^manim/grpc/gen/
- repo: https://github.com/pre-commit/pygrep-hooks
rev: v1.9.0
hooks:
- id: python-check-blanket-noqa
name: Precision flake ignores
- repo: https://github.com/psf/black
rev: 21.8b0
hooks:
- id: black
exclude: ^manim/grpc/gen/
- repo: https://github.com/asottile/blacken-docs
rev: v1.11.0
hooks:
- id: blacken-docs
additional_dependencies: [black==20.8b1]
- repo: https://github.com/asottile/yesqa
rev: v1.2.3
hooks:
- id: yesqa
name: Remove unneeded flake ignores
- repo: https://github.com/PyCQA/flake8
rev: 3.9.2
hooks:
- id: flake8
additional_dependencies: [flake8-builtins==1.5.3, flake8-bugbear==21.4.3, flake8-docstrings==1.6.0, flake8-rst-docstrings==0.2.3]
additional_dependencies: [flake8-builtins==1.5.3, flake8-bugbear==21.4.3,
flake8-docstrings==1.6.0, flake8-rst-docstrings==0.2.3,
flake8-pytest-style==1.5.0, flake8-simplify==0.14.1, flake8-comprehensions==3.6.1]
- repo: https://github.com/codespell-project/codespell
rev: v2.1.0
hooks:

View file

@ -1,6 +1,6 @@
# YAML 1.2
---
authors:
authors:
-
name: "The Manim Community Developers"
cff-version: "1.1.0"
@ -10,4 +10,4 @@ message: "We acknowledge the importance of good software to support research, an
title: Manim Mathematical Animation Framework
url: "https://www.manim.community/"
version: "v0.10.0"
...
...

View file

@ -204,7 +204,7 @@ Some team members may have a conflict of interest and may be excluded from discu
Once the team has approved the behavioral modification plans and consequences, they will communicate the recommended response to the Manim Community moderators. The team should not state who reported this incident. They should attempt to anonymize any identifying information from the report.
Moderators are required to respond with whether they accept the recommended response to the report. If they disagree with the recommended response, they should provide a detailed response or additional context as to why they disagree. Moderators are encouraged to respond within a week.
Moderators are required to respond with whether they accept the recommended response to the report. If they disagree with the recommended response, they should provide a detailed response or additional context as to why they disagree. Moderators are encouraged to respond within a week.
In cases where the moderators disagree on the suggested resolution for a report, the Manim Community Code of Conduct team may choose to notify the Manim Community Moderators.

View file

@ -169,7 +169,7 @@ We acknowledge the importance of good software to support research, and we note
that research becomes more valuable when it is communicated effectively. To
demonstrate the value of Manim, we ask that you cite Manim in your work.
Currently, the best way to cite Manim is to go to our
[repository page](https://github.com/ManimCommunity/manim) (if you aren't already) and
[repository page](https://github.com/ManimCommunity/manim) (if you aren't already) and
click the "cite this repository" button on the right sidebar. This will generate
a citation in your preferred format, and will also integrate well with citation managers.

View file

@ -13,4 +13,3 @@ Multi-platform builds are possible by running
docker buildx build --push --platform linux/arm64/v8,linux/amd64 --tag manimcommunity/manim:TAG -f docker/Dockerfile .
```
from the root directory of the repository.

View file

@ -7,4 +7,4 @@ TEXMFSYSCONFIG /usr/local/texlive/texmf-config
TEXMFSYSVAR /usr/local/texlive/texmf-var
TEXMFVAR ~/.texlive/texmf-var
option_doc 0
option_src 0
option_src 0

View file

@ -44,16 +44,16 @@ window.addEventListener("load", function () {
.node text {
fill: ${colors.text};
}
.node polygon {
fill: ${colors.box};
}
.edge polygon {
fill: ${colors.edge};
stroke: ${colors.edge};
}
.edge path {
stroke: ${colors.edge};
}

View file

@ -115,4 +115,4 @@ Other Changes
#. Cleanup 3b1b Specific Files
#. Rename package from manimlib to manim
#. Move all imports to :code:`__init__`, so :code:`from manim import *` replaces :code:`from manimlib.imports import *`
#. Global dir variable handling has been removed. Instead :code:`initialize_directories`, if needed, overrides the values from the cfg files at runtime.
#. Global dir variable handling has been removed. Instead :code:`initialize_directories`, if needed, overrides the values from the cfg files at runtime.

View file

@ -77,7 +77,7 @@ Breaking changes
----------------
* `#1843 <https://github.com/ManimCommunity/manim/pull/1843>`__: Dropped redundant OpenGL files and add metaclass support for :class:`~.Surface`
- ``OpenGL<x>`` classes from ``opengl_geometry.py``, ``opengl_text_mobject.py``, ``opengl_tex_mobject.py``, ``opengl_svg_path.py``, ``opengl_svg_mobject.py`` and most of ``opengl_three_dimensions.py`` have been removed.
- ``OpenGL<x>`` classes from ``opengl_geometry.py``, ``opengl_text_mobject.py``, ``opengl_tex_mobject.py``, ``opengl_svg_path.py``, ``opengl_svg_mobject.py`` and most of ``opengl_three_dimensions.py`` have been removed.
- ``ParametricSurface`` has been renamed to :class:`~.Surface`
Deprecated classes and functions
@ -280,5 +280,3 @@ New releases
------------
* `#1989 <https://github.com/ManimCommunity/manim/pull/1989>`__: Prepare new release v0.10.0

View file

@ -90,4 +90,3 @@ Other changes
- Change several ``str.format()`` to ``f``-strings (:pr:`867`)
- Update javascript renderer (:pr:`830`)
- Bump version number to 0.2.0, update changelog (:pr:`894`)

View file

@ -161,7 +161,7 @@ Fixed bugs
* `#1134 <https://github.com/ManimCommunity/manim/pull/1134>`__: Fixed the `-a` flag.
The ``-a`` / ``--write-all`` flag was broken. When used, it would cause Manim to crash just after beginning to render the second scene.
* `#1115 <https://github.com/ManimCommunity/manim/pull/1115>`__: Fixed bugs in :class:`~.OpenGLMobject` and added :class:`ApplyMethod` support
* `#1115 <https://github.com/ManimCommunity/manim/pull/1115>`__: Fixed bugs in :class:`~.OpenGLMobject` and added :class:`ApplyMethod` support
Fixed undefined variables and converted :class:`Mobject` to :class:`OpenGLMobject`. Also, fixed assert statement in :class:`ApplyMethod`.
* `#1092 <https://github.com/ManimCommunity/manim/pull/1092>`__: Refactored coordinate_systems.py, fixed bugs, added :class:`~.NumberPlane` test
@ -297,11 +297,10 @@ Code quality improvements and similar refactors
* `#1019 <https://github.com/ManimCommunity/manim/pull/1019>`__: Refactored :meth:`~.Scene.play`
- Removed the _**three**_ decorators of :meth:`~.Scene.play`, in particular: caching logic and file writer logic are now included within :meth:`~.Scene.play` (it wasn't possible before, because `scene.wait` and `scene.play` were two different things).
- Added `is_static_wait` attributes to Wait. (<=> if wait is a frozen frame).
- Renamed and moved `scene.add_static_frame` to `renderer.freeze_current_frame`.
- Added `is_static_wait` attributes to Wait. (<=> if wait is a frozen frame).
- Renamed and moved `scene.add_static_frame` to `renderer.freeze_current_frame`.
- Now when calling play without animation, it raises `ValueError` instead of just a warning.
- Fixed :pr:`874` by modifying `renderer.update_skipping_status`
- `renderer` starts the animation with `scene.begin_animations` (`scene.compile_animation_data` used to do this)
- The run time and the time progression generation is now done in `scene.play_internal` although it'd make more sense that renderer processes it later.
- The run time and the time progression generation is now done in `scene.play_internal` although it'd make more sense that renderer processes it later.
- Added a bunch of cool tests thanks to mocks, and thanks to the new syntax `scene.render`

View file

@ -473,4 +473,3 @@ New releases
------------
* `#1434 <https://github.com/ManimCommunity/manim/pull/1434>`__: Prepare v0.6.0

View file

@ -140,7 +140,7 @@ New features
* `#1559 <https://github.com/ManimCommunity/manim/pull/1559>`__: Update VGroup to support item assignment (#1530)
Support indexed item-assignment for VGroup
* `#1518 <https://github.com/ManimCommunity/manim/pull/1518>`__: Allow fading multiple Mobjects in one Animation
* `#1518 <https://github.com/ManimCommunity/manim/pull/1518>`__: Allow fading multiple Mobjects in one Animation
* `#1422 <https://github.com/ManimCommunity/manim/pull/1422>`__: Added :func:`~.override_animation` decorator
@ -190,7 +190,7 @@ Enhancements
* `#1567 <https://github.com/ManimCommunity/manim/pull/1567>`__: Compatibility Fixes with ManimPango v0.3.0
- ManimPango v0.3.0+ is required for Manim now.
- ManimPango v0.3.0+ is required for Manim now.
- Show errors from Pango when Markup isn't correct
* `#1512 <https://github.com/ManimCommunity/manim/pull/1512>`__: OpenGL compatibility via metaclass: graph
@ -244,7 +244,7 @@ Fixed bugs
* `#1560 <https://github.com/ManimCommunity/manim/pull/1560>`__: Declare ``*.npz`` ``*.wav`` ``*.png`` as binary in ``.gitattributes``
* `#1211 <https://github.com/ManimCommunity/manim/pull/1211>`__: Refactored scene caching and fixed issue when a different hash was produced when copying a mobject in the scene
* `#1211 <https://github.com/ManimCommunity/manim/pull/1211>`__: Refactored scene caching and fixed issue when a different hash was produced when copying a mobject in the scene
Refactored internal scene-caching mechanism and fixed bug when an inconsistent hash was produced when copying a mobject.
* `#1527 <https://github.com/ManimCommunity/manim/pull/1527>`__: Improved handling of substring isolation within sqrt, and fixed a bug with transform_mismatch for the matching shape transforms
@ -342,7 +342,7 @@ Changes to our development infrastructure
* `#1499 <https://github.com/ManimCommunity/manim/pull/1499>`__: Updated Discord links in the docs to point towards a standardized redirect
* `#1461 <https://github.com/ManimCommunity/manim/pull/1461>`__: Build the docs - Logging
* `#1461 <https://github.com/ManimCommunity/manim/pull/1461>`__: Build the docs - Logging
* `#1481 <https://github.com/ManimCommunity/manim/pull/1481>`__: pyproject.toml: poetry_core -> poetry-core
@ -397,5 +397,3 @@ New releases
------------
* `#1601 <https://github.com/ManimCommunity/manim/pull/1601>`__: Preparation for v0.7.0: added changelog and bumped version number

View file

@ -332,5 +332,3 @@ New releases
------------
* `#1738 <https://github.com/ManimCommunity/manim/pull/1738>`__: Preparation for v0.8.0: added changelog and bumped version number

View file

@ -278,5 +278,3 @@ New releases
------------
* `#1850 <https://github.com/ManimCommunity/manim/pull/1850>`__: Bump version number to ``v0.9.0`` and generate changelog

View file

@ -142,7 +142,11 @@ inheritance_graph_attrs = dict(
)
inheritance_node_attrs = dict(
penwidth=0, shape="box", width=0.05, height=0.05, margin=0.05
penwidth=0,
shape="box",
width=0.05,
height=0.05,
margin=0.05,
)
inheritance_edge_attrs = dict(

View file

@ -40,22 +40,22 @@ For first-time contributors
.. code-block:: shell
git remote add upstream https://github.com/ManimCommunity/manim.git
#. Now, ``git remote -v`` should show two remote repositories named:
- ``origin``, your forked repository
- ``upstream`` the ManimCommunity repository
#. Install Manim:
- Follow the steps in our :doc:`installation instructions
- Follow the steps in our :doc:`installation instructions
<../installation>` to install **Manim's dependencies**,
primarily ``ffmpeg`` and ``LaTeX``.
- We recommend using `Poetry <https://python-poetry.org>`__ to manage your
developer installation of Manim. Poetry is a tool for dependency
management and packaging in Python. It allows you to declare the libraries
your project depends on, and it will manage (install / update) them
your project depends on, and it will manage (install / update) them
for you. In addition, Poetry provides a simple interface for
managing virtual environments.
@ -65,7 +65,7 @@ For first-time contributors
your cloned repository. Poetry will then install Manim, as well
as create and enter a virtual environment. You can always re-enter
that environment by running ``poetry shell``.
- In case you decided against Poetry, you can install Manim via pip
by running ``python3 -m pip install .``. Note that due to our
development infrastructure being based on Poetry, we currently
@ -83,7 +83,7 @@ For first-time contributors
.. code-block:: shell
poetry run pre-commit install
This will ensure during development that each of your commits is properly
formatted against our linter and formatters, ``black``, ``flake8``,
``isort`` and ``codespell``.
@ -118,7 +118,7 @@ Develop your contribution
``git add .``, or add specific files with
.. code-block:: shell
git add <file/directory>
and commit these changes to your local history with ``git commit``. If you
@ -126,7 +126,7 @@ Develop your contribution
hooks fail.
.. tip::
When crafting commit messages, it is highly recommended that
you adhere to `these guidelines <https://www.conventionalcommits.org/en/v1.0.0/>`_.
@ -226,7 +226,7 @@ sticks to our coding conventions.
and `flake8 <https://flake8.pycqa.org/en/latest/>`_. The GitHub pipeline
makes sure that the (Python) files changed in your pull request
also adhere to this code style. If this step of the pipeline fails,
fix your code formatting automatically by running ``black <file or directory>`` and ``isort <file or directory>``.
fix your code formatting automatically by running ``black <file or directory>`` and ``isort <file or directory>``.
To fix code style problems, run ``flake8 <file or directory>`` for a style report, and then fix the problems
manually that were detected by ``flake8``.
@ -267,7 +267,7 @@ Further useful guidelines
to them in your new issue (even if the old ones are closed).
#. When submitting a code review, it is highly recommended that you adhere to
`these general guidelines <https://conventionalcomments.org/>`_.
`these general guidelines <https://conventionalcomments.org/>`_.
#. If you find stale or inactive issues that seem to be irrelevant, please post
a comment saying 'This issue should be closed', and a community developer

View file

@ -160,7 +160,7 @@ Example:
d: "SomeClassFromFarAway",
test: Optional[int] = 45
) -> "EpicClassInThisFile": # typings are optional for now
"""My cool function. Builds and modifies an :class:`EpicClassInThisFile` instance with the given
"""My cool function. Builds and modifies an :class:`EpicClassInThisFile` instance with the given
parameters.
Parameters

View file

@ -2,23 +2,23 @@
Adding Examples
===============
This is a page for adding examples to the documentation.
This is a page for adding examples to the documentation.
Here are some guidelines you should follow before you publish your examples.
Guidelines for examples
-----------------------
Everybody is welcome to contribute examples to the documentation. Since straightforward
Everybody is welcome to contribute examples to the documentation. Since straightforward
examples are a great resource for quickly learning manim, here are some guidelines.
What makes a great example
--------------------------
.. note::
.. note::
As soon as a new version of manim is released, the documentation will be a snapshot of that
As soon as a new version of manim is released, the documentation will be a snapshot of that
version. Examples contributed after the release will only be shown in the latest documentation.
* Examples should be ready to copy and paste for use.
* Examples should be brief yet still easy to understand.
@ -47,7 +47,7 @@ How examples are structured
Writing examples
~~~~~~~~~~~~~~~~
When you want to add/edit examples, they can be found in the ``docs/source/`` directory, or directly in the manim source code (e.g. ``manim/mobject/mobject.py``). The examples are written in
When you want to add/edit examples, they can be found in the ``docs/source/`` directory, or directly in the manim source code (e.g. ``manim/mobject/mobject.py``). The examples are written in
``rst`` format and use the manim directive (see :mod:`~.manim_directive` ), ``.. manim::``. Every example is in its own block, and looks like this:
.. code:: rst
@ -64,8 +64,8 @@ When you want to add/edit examples, they can be found in the ``docs/source/`` di
self.add(t)
self.wait(1)
In the building process of the docs, all ``rst`` files are scanned, and the
manim directive (``.. manim::``) blocks are identified as scenes that will be run
In the building process of the docs, all ``rst`` files are scanned, and the
manim directive (``.. manim::``) blocks are identified as scenes that will be run
by the current version of manim.
Here is the syntax:
@ -84,7 +84,7 @@ has the same name: ``class Formula1(Scene)``.
Sometimes, when you reload an example in your browser, it has still the old
website somewhere in its cache. If this is the case, delete the website cache,
or open a new incognito tab in your browser, then the latest docs
should be shown.
should be shown.
**Only for locally built documentation:** If this still doesn't work, you may need
to delete the contents of ``docs/source/references`` before rebuilding
the documentation.
the documentation.

View file

@ -134,4 +134,4 @@ Example: ``List[Optional[:class:`str`]]`` for a list that returns
elements that are either a ``str`` or ``None``;
``Tuple[:class:`str`, :class:`int`]`` for a tuple of type
``(str, int)``; ``Tuple[:class:`int`, ...]`` for a tuple of variable
length with only integers.
length with only integers.

View file

@ -8,20 +8,20 @@ feature has been broken and/or been unintentionally modified.
How Manim tests
---------------
Manim uses pytest as its testing framework.
To start the testing process, go to the root directory of the project and run pytest in your terminal.
Manim uses pytest as its testing framework.
To start the testing process, go to the root directory of the project and run pytest in your terminal.
Any errors that occur during testing will be displayed in the terminal.
Some useful pytest flags:
Some useful pytest flags:
- ``-x`` will make pytest stop at the first failure it encounters
- ``-s`` will make pytest display all the print messages (including those during scene generation, like DEBUG messages)
- ``--skip_slow`` will skip the (arbitrarily) slow tests
- ``--show_diff`` will show a visual comparison in case a unit test is failing.
How it Works
~~~~~~~~~~~~
@ -129,7 +129,7 @@ The Main Directories
- ``test_graphical_units/``:
Contains graphical tests.
- ``test_scene_rendering/``:
For tests that need to render a scene in some way, such as tests for CLI
@ -169,7 +169,7 @@ For example, to test the ``Circle`` VMobject which resides in
The name of the module is indicated by the variable __module_test__, that **must** be declared in any graphical test file. The module name is used to store the graphical control data.
.. important::
You will need to use the ``frames_comparison`` decorator to create a test. The test function **must** accept a
You will need to use the ``frames_comparison`` decorator to create a test. The test function **must** accept a
parameter named ``scene`` that will be used like ``self`` in a standard ``construct`` method.
Here's an example in ``test_geometry.py``:
@ -196,7 +196,7 @@ The decorator can be used with or without parentheses. **By default, the test on
circle = Circle()
scene.play(Animation(circle))
You can also specify, when needed, which base scene you need (ThreeDScene, for example) :
You can also specify, when needed, which base scene you need (ThreeDScene, for example) :
.. code:: python
@ -211,16 +211,16 @@ Note that tests name must follow the syntax ``test_<thing_to_test>``, otherwise
.. warning::
If you run pytest now, you will get a ``FileNotFound`` error. This is because
you have not created control data for your test.
you have not created control data for your test.
To create the control data for your test, you have to use the flag ``--set_test`` along with pytest.
For the example above, it would be
To create the control data for your test, you have to use the flag ``--set_test`` along with pytest.
For the example above, it would be
.. code-block:: bash
pytest test_geometry.py::test_circle --set_test -s
(``-s`` is here to see manim logs, so you can see what's going on).
(``-s`` is here to see manim logs, so you can see what's going on).
Please make sure to add the control data to git as soon as it is produced with ``git add <your-control-data.npz>``.
@ -251,7 +251,7 @@ To test videos generated, we use the decorator
out, err, exit_code = capture(command)
assert exit_code == 0, err
.. note:: ``assert exit*\ code == 0, err`` is used in case of the command fails
.. note:: ``assert exit*\ code == 0, err`` is used in case of the command fails
to run. The decorator takes two arguments: json name and the path
to where the video should be generated, starting from the ``media/`` dir.

View file

@ -75,13 +75,13 @@ When adding type hints to manim, there are some guidelines that should be follow
.. note::
As a helper for tool for typesets, you can use `typestring-parser
<https://github.com/Dominik1123/typestring-parser>`_
<https://github.com/Dominik1123/typestring-parser>`_
which can be accessed by first installing it via ``pip`` - ``pip install typestring-parser`` and
then using ``from typestring_parser import parse``.
.. doctest::
:options: +SKIP
>>> from typestring_parser import parse
>>> parse("int")
<class 'int'>
@ -100,4 +100,4 @@ Missing Sections for typehints are:
* Where to find the alias
* When to use Object and when to use "Object".
* The use of a TypeVar on the type hints for copy().
* The definition and use of Protocols (like Sized, or Sequence, or Iterable...)
* The definition and use of Protocols (like Sized, or Sequence, or Iterable...)

View file

@ -322,7 +322,7 @@ Plotting with Manim
x_range=[0, 10], y_range=[0, 100, 10], axis_config={"include_tip": False}
)
labels = ax.get_axis_labels(x_label="x", y_label="f(x)")
t = ValueTracker(0)
def func(x):
@ -570,7 +570,7 @@ Special Camera Settings
.. manim:: ThreeDSurfacePlot
:save_last_frame:
:ref_classes: ThreeDScene Surface
class ThreeDSurfacePlot(ThreeDScene):
def construct(self):
resolution_fa = 42

View file

@ -11,7 +11,7 @@ Otherwise, if you intend to use Manim to work on an animation project,
we recommend installing the library locally (either to your system's
Python, or via Docker).
.. warning::
.. warning::
Note that there are several different versions of Manim. The
instructions on this website are **only** for the *community edition*.
@ -21,7 +21,7 @@ Python, or via Docker).
#. :ref:`Installing Manim to your system's Python <local-installation>`
#. :ref:`Using Manim via Docker <docker-installation>`
#. :ref:`Interactive Jupyter notebooks via Binder / Google Colab
#. :ref:`Interactive Jupyter notebooks via Binder / Google Colab
<interactive-online>`
@ -43,7 +43,7 @@ operating system specific instructions for you to follow.
follow the steps on the following pages carefully, but in case
you hit a wall we are happy to help: either `join our Discord
<https://www.manim.community/discord/>`__, or start a new
Discussion `directly on GitHub
Discussion `directly on GitHub
<https://github.com/ManimCommunity/manim/discussions>`__.
.. toctree::
@ -59,12 +59,12 @@ Once Manim is installed locally, you can proceed to our
through rendering a first simple scene.
As mentioned above, do not worry if there are errors or other
problems: consult our :doc:`troubleshooting
problems: consult our :doc:`troubleshooting
guide <installation/troubleshooting>` for help, or get in touch
with the community via `GitHub discussions
<https://github.com/ManimCommunity/manim/discussions>`__ or
with the community via `GitHub discussions
<https://github.com/ManimCommunity/manim/discussions>`__ or
`Discord <https://www.manim.community/discord/>`__.
.. _docker-installation:
@ -108,6 +108,3 @@ In order to change code in the library, it is recommended to
install Manim in a different way. Please follow the instructions
in our :doc:`contribution guide <contributing>` if you are
interested in that.

View file

@ -2,19 +2,19 @@ Docker
======
The community maintains a docker image, which can be found
`on DockerHub <https://hub.docker.com/r/manimcommunity/manim>`__.
`on DockerHub <https://hub.docker.com/r/manimcommunity/manim>`__.
For our image ``manimcommunity/manim``, there are the following tags:
- ``latest``: the most recent version corresponding
- ``latest``: the most recent version corresponding
to `the main branch <https://github.com/ManimCommunity/manim>`__,
- ``stable``: the latest released version (according to
- ``stable``: the latest released version (according to
`the releases page <https://github.com/ManimCommunity/manim/releases>`__),
- ``vX.Y.Z``: any particular released version (according to
- ``vX.Y.Z``: any particular released version (according to
`the releases page <https://github.com/ManimCommunity/manim/releases>`__).
.. note::
When using Manim's CLI within a Docker container, some flags like
When using Manim's CLI within a Docker container, some flags like
``-p`` (preview file) and ``-f`` (show output file in the file browser)
are not supported.
@ -23,7 +23,7 @@ Basic usage of the Docker container
-----------------------------------
Assuming that you can access the docker installation on your system
from a terminal (bash / PowerShell) via ``docker``, you can
from a terminal (bash / PowerShell) via ``docker``, you can
render a scene ``CircleToSquare`` in a file `test_scenes.py`
with the following command.
@ -45,7 +45,7 @@ modify to your liking. First, run
.. code-block:: sh
docker run -it --name my-manim-container -v "/full/path/to/your/directory:/manim" manimcommunity/manim /bin/bash
docker run -it --name my-manim-container -v "/full/path/to/your/directory:/manim" manimcommunity/manim /bin/bash
to obtain an interactive shell inside your container allowing you
@ -75,4 +75,4 @@ local JupyterLab instance. To do that, simply run
docker run -it -p 8888:8888 manimcommunity/manim jupyter lab --ip=0.0.0.0
and then follow the instructions in the terminal.
and then follow the instructions in the terminal.

View file

@ -29,12 +29,12 @@ a way that allows them to be shared interactively via Binder as well:
FROM manimcommunity/manim:v0.9.0
COPY --chown=manimuser:manimuser . /manim
Don't forget to change the version tag ``v0.9.0`` to the version you
were working with locally when creating your notebooks.
#. Make the directory with your worksheets and the ``Dockerfile``
available to the public (and in particular: to Binder!). There are
`several different options to do so
`several different options to do so
<https://mybinder.readthedocs.io/en/latest/introduction.html#how-can-i-prepare-a-repository-for-binder>`__,
within the community we usually work with GitHub
repositories or gists.
@ -44,7 +44,7 @@ a way that allows them to be shared interactively via Binder as well:
.. hint::
The repository containing our `interactive tutorial
The repository containing our `interactive tutorial
<https://try.manim.community>`__ can be found at
https://github.com/ManimCommunity/jupyter_examples.
@ -88,12 +88,12 @@ in a new code cell. Then create another cell containing the
following code::
%%manim -qm -v WARNING SquareToCircle
class SquareToCircle(Scene):
def construct(self):
square = Square()
circle = Circle()
circle.set_fill(PINK, opacity=0.5)
circle = Circle()
circle.set_fill(PINK, opacity=0.5)
self.play(Create(square))
self.play(Transform(square, circle))
self.wait()

View file

@ -6,7 +6,7 @@ system and package manager. If you happen to know exactly what you are doing,
you can also simply ensure that your system has:
- a reasonably recent version of Python 3 (3.7 or above),
- with working Cairo bindings in the form of
- with working Cairo bindings in the form of
`pycairo <https://cairographics.org/pycairo/>`__,
- FFmpeg accessible from the command line as ``ffmpeg``,
- and `Pango <https://pango.gnome.org>`__ headers.
@ -20,10 +20,10 @@ Then, installing Manim is just a matter of running:
.. note::
In light of the current efforts of migrating to rendering via OpenGL,
this list might be incomplete. Please `let us know
this list might be incomplete. Please `let us know
<https://github.com/ManimCommunity/manim/issues/new/choose>` if you
ran into missing dependencies while installing.
In any case, we have also compiled instructions for several common
combinations of operating systems and package managers below.
@ -38,13 +38,13 @@ simply run:
.. code-block:: bash
sudo apt update
sudo apt update
sudo apt install libcairo2-dev libpango1.0-dev ffmpeg
If you don't have python3-pip installed, install it via:
.. code-block:: bash
sudo apt install python3-pip
Then, to install Manim, run:
@ -95,11 +95,11 @@ pacman  Arch / Manjaro
.. tip::
Thanks to *groctel*, there is a `dedicated Manim package
Thanks to *groctel*, there is a `dedicated Manim package
on the AUR! <https://aur.archlinux.org/packages/manim/>`
If you don't want to use the packaged version from AUR, here is what
you need to do manually: Update your package sources, then install
you need to do manually: Update your package sources, then install
Cairo, Pango, and FFmpeg:
.. code-block:: bash
@ -110,7 +110,7 @@ Cairo, Pango, and FFmpeg:
If you don't have ``python-pip`` installed, get it by running:
.. code-block:: bash
sudo pacman -S python-pip
then simply install Manim via:
@ -134,7 +134,7 @@ equations, LaTeX has to be installed as well. Note that this is an optional
dependency: if you don't intend to use LaTeX, you don't have to install it.
You can use whichever LaTeX distribution you like or whichever is easiest
to install with your package manager. Usually,
to install with your package manager. Usually,
`TeX Live <https://www.tug.org/texlive/>`__ is a good candidate if you don't
care too much about disk space.

View file

@ -16,7 +16,7 @@ follow `Homebrew's installation instructions <https://docs.brew.sh/Installation>
layer between Intel and ARM architectures. This is no longer necessary, Manim can
(and is recommended to) be installed natively.
Required Dependencies
---------------------
@ -28,7 +28,7 @@ and some required Python packages), run:
brew install py3cairo ffmpeg
On *Apple Silicon* based machines (i.e., devices with the M1 chip or similar; if
you are unsure which processor you have check by opening the Apple menu, select
you are unsure which processor you have check by opening the Apple menu, select
*About This Mac* and check the entry next to *Chip*), some additional dependencies
are required, namely:
@ -66,7 +66,7 @@ In order to make use of Manim's interface to LaTeX for, e.g., rendering
equations, LaTeX has to be installed as well. Note that this is an optional
dependency: if you don't intend to use LaTeX, you don't have to install it.
For MacOS, the recommended LaTeX distribution is
For MacOS, the recommended LaTeX distribution is
`MacTeX <http://www.tug.org/mactex/>`__. You can install it by following
the instructions from the link, or alternatively also via Homebrew by
running:
@ -79,7 +79,7 @@ running:
MacTeX is a *full* LaTeX distribution and will require more than 4GB of
disk space. If this is an issue for you, consider installing a smaller
distribution like
distribution like
`BasicTeX <http://www.tug.org/mactex/morepackages.html>`__.
Should you choose to work with some partial TeX distribution, the full list

View file

@ -6,14 +6,14 @@ Version incompatibility
Confusion and conflict between versions is by far the most common reason
for installation failures. Some signs and errors resulting from this are
as follows:
as follows:
- ``There are no scenes in that module``
- ``ModuleNotFoundError: No module named 'manim'``
- ``ModuleNotFoundError: No module named 'manimlib'``
- You followed any tutorial created before October 2020 (because the community edition did not exist before then)
- You cloned a repository on GitHub (installation of the community version for normal use does not require the cloning of any repository)
- Different import statements (explained below)
- ``There are no scenes in that module``
- ``ModuleNotFoundError: No module named 'manim'``
- ``ModuleNotFoundError: No module named 'manimlib'``
- You followed any tutorial created before October 2020 (because the community edition did not exist before then)
- You cloned a repository on GitHub (installation of the community version for normal use does not require the cloning of any repository)
- Different import statements (explained below)
- You used documentation for multiple versions (such as the readme for 3b1b/manim and this documentation)
.. note::
@ -41,7 +41,7 @@ generally not work without some modification.
Identifying the version you are running
---------------------------------------
The community edition of manim should always state `Manim Community <version_number>`
The community edition of manim should always state `Manim Community <version_number>`
as its first line of any command you run.
Identifying and removing conflicting versions of manim
@ -120,7 +120,7 @@ First, make sure your ``dvisvgm`` version is at least 2.4:
If you do not know how to update ``dvisvgm``, please refer to your operating system's documentation.
Second, check whether your ``dvisvgm`` supports PostScript specials. This is
Second, check whether your ``dvisvgm`` supports PostScript specials. This is
needed to convert from PDF to SVG.
.. code-block:: bash
@ -128,7 +128,7 @@ needed to convert from PDF to SVG.
dvisvgm -l
If the output to this command does **not** contain ``ps dvips PostScript specials``,
If the output to this command does **not** contain ``ps dvips PostScript specials``,
this is a bad sign. In this case, run
.. code-block:: bash
@ -136,16 +136,16 @@ this is a bad sign. In this case, run
dvisvgm -h
If the output does **not** contain ``--libgs=filename``, this means your
If the output does **not** contain ``--libgs=filename``, this means your
``dvisvgm`` does not currently support PostScript. You must get another binary.
If, however, ``--libgs=filename`` appears in the help, that means that your
``dvisvgm`` needs the Ghostscript library to support PostScript. Search for
``libgs.so`` (on Linux, probably in ``/usr/local/lib`` or ``/usr/lib``) or
``gsdll32.dll`` (on 32-bit Windows, probably in ``C:\windows\system32``) or
``gsdll64.dll`` (on 64-bit Windows, probably in ``c:\windows\system32`` -- yes
32) or ``libgsl.dylib`` (on Mac OS, probably in ``/usr/local/lib`` or
``/opt/local/lib``). Please look carefully, as the file might be located
If, however, ``--libgs=filename`` appears in the help, that means that your
``dvisvgm`` needs the Ghostscript library to support PostScript. Search for
``libgs.so`` (on Linux, probably in ``/usr/local/lib`` or ``/usr/lib``) or
``gsdll32.dll`` (on 32-bit Windows, probably in ``C:\windows\system32``) or
``gsdll64.dll`` (on 64-bit Windows, probably in ``c:\windows\system32`` -- yes
32) or ``libgsl.dylib`` (on Mac OS, probably in ``/usr/local/lib`` or
``/opt/local/lib``). Please look carefully, as the file might be located
elsewhere, e.g. in the directory where Ghostscript is installed.
As soon as you have found the library, try (on Mac OS or Linux)
@ -163,8 +163,8 @@ or (on Windows)
dvisvgm -l
You should now see ``ps dvips PostScript specials`` in the output. Refer to
your operating system's documentation to find out how you can set or export the
You should now see ``ps dvips PostScript specials`` in the output. Refer to
your operating system's documentation to find out how you can set or export the
environment variable ``LIBGS`` automatically whenever you open a shell.
As a last check, you can run
@ -173,12 +173,12 @@ As a last check, you can run
dvisvgm -V1
while still having ``LIBGS`` set to the correct path, of course. If ``dvisvgm``
can find your Ghostscript installation, it will be shown in the output together
while still having ``LIBGS`` set to the correct path, of course. If ``dvisvgm``
can find your Ghostscript installation, it will be shown in the output together
with the version number.
If you do not have the necessary library on your system, please refer to your
operating system's documentation to find out where you can get it and how you
If you do not have the necessary library on your system, please refer to your
operating system's documentation to find out where you can get it and how you
have to install it.
If you are unable to solve your problem, check out the `dvisvgm FAQ <https://dvisvgm.de/FAQ/>`_.

View file

@ -1,24 +1,24 @@
Differences between Manim Versions
==================================
While originally a single library, there are now three main versions of manim,
each with their own advantages, disadvantages, and ideal use cases.
It is important to understand these differences in order to select the best version
While originally a single library, there are now three main versions of manim,
each with their own advantages, disadvantages, and ideal use cases.
It is important to understand these differences in order to select the best version
for your use case and avoid confusion arising from version mismatches.
A brief history of Manim
************************
Manim was originally created by Grant Sanderson as a personal project and for use in his YouTube channel,
`3Blue1Brown <https://www.youtube.com/channel/UCYO_jab_esuFRV4b17AJtAw>`_. As his channel gained popularity,
many grew to like the style of his animations and wanted to use manim for their own projects.
However, as manim was only intended for personal use,
Manim was originally created by Grant Sanderson as a personal project and for use in his YouTube channel,
`3Blue1Brown <https://www.youtube.com/channel/UCYO_jab_esuFRV4b17AJtAw>`_. As his channel gained popularity,
many grew to like the style of his animations and wanted to use manim for their own projects.
However, as manim was only intended for personal use,
it was very difficult for other users to install and use it.
In late 2019, Grant started working on faster OpenGL rendering in a new branch,
known as the shaders branch. In mid-2020, a group of developers forked it into what is now the community edition;
this is the version documented on this website.
In early 2021, Grant merged the shaders branch back into master, making it the default branch in his repository.
In late 2019, Grant started working on faster OpenGL rendering in a new branch,
known as the shaders branch. In mid-2020, a group of developers forked it into what is now the community edition;
this is the version documented on this website.
In early 2021, Grant merged the shaders branch back into master, making it the default branch in his repository.
The old version is still available as the branch ``cairo-backend``.
The three versions of Manim
@ -32,8 +32,8 @@ There are currently three main versions of manim. They are as follows:
Which version to use
********************
We recommend using the community edition for most purposes, as it has been developed to be more stable,
better tested, quicker to respond to community contributions, and easier for beginners to use.
We recommend using the community edition for most purposes, as it has been developed to be more stable,
better tested, quicker to respond to community contributions, and easier for beginners to use.
It also has partial experimental OpenGL support and should have full support shortly (as of April 2021).
If you would like to use a version with full OpenGL support or render recent 3Blue1Brown videos (2020 onwards), you should use ManimGL.
@ -42,8 +42,8 @@ If you would like to render old 3Blue1Brown projects (2019 and before), you shou
Notes on installation, documentation, and use
*********************************************
If you are a beginner, it is very important that you only use the documentation for your desired version.
Trying to install or learn manim using documentation or guides made for different versions will likely fail and only lead to more confusion.
As many tutorials and guides on the internet are outdated, we do not recommend you follow them.
You should only read tutorials and documentation for other versions once you are aware of the differences between them
If you are a beginner, it is very important that you only use the documentation for your desired version.
Trying to install or learn manim using documentation or guides made for different versions will likely fail and only lead to more confusion.
As many tutorials and guides on the internet are outdated, we do not recommend you follow them.
You should only read tutorials and documentation for other versions once you are aware of the differences between them
and know how to adapt code for your desired version.

View file

@ -2,7 +2,7 @@ Windows
=======
The easiest way of installing Manim and its dependencies is by using a
package manager like `Chocolatey <https://chocolatey.org/>`__
package manager like `Chocolatey <https://chocolatey.org/>`__
or `Scoop <https://scoop.sh>`__. If you are not afraid of editing
your System's ``PATH``, a manual installation is also possible.
In fact, if you already have an existing Python
@ -11,7 +11,7 @@ everything up and running.
If you choose to use one of the package managers, please follow
their installation instructions
(`for Chocolatey <https://chocolatey.org/install#install-step2>`__,
(`for Chocolatey <https://chocolatey.org/install#install-step2>`__,
`for Scoop <https://scoop-docs.now.sh/docs/getting-started/Quick-Start.html>`__)
to make one of them available on your system.
@ -69,24 +69,24 @@ installed on your system.
We have received reports of problems caused by using the version of
Python that can be installed from the Windows Store. At this point,
we recommend staying away from the Windows Store version. Instead,
install Python directly from the
install Python directly from the
`official website <https://www.python.org>`__.
**FFmpeg:** In order to install FFmpeg, you can get a
pre-compiled and ready-to-use version from one of the resources
linked at https://ffmpeg.org/download.html#build-windows, such as
`the version available here
`the version available here
<https://www.gyan.dev/ffmpeg/builds/ffmpeg-release-essentials.7z>`__
(recommended), or if you know exactly what you are doing
you can alternatively get the source code
from https://ffmpeg.org/download.html and compile it yourself.
After downloading the pre-compiled archive,
After downloading the pre-compiled archive,
`unzip it <https://www.7-zip.org>`__ and, if you like, move the
extracted directory to some more permanent place (e.g.,
extracted directory to some more permanent place (e.g.,
``C:\Program Files\``). Next, edit the ``PATH`` environment variable:
first, visit ``Control Panel`` > ``System`` > ``System settings`` >
first, visit ``Control Panel`` > ``System`` > ``System settings`` >
``Environment Variables``, then add the full path to the ``bin``
directory inside of the (moved) ffmpeg directory to the
``PATH`` variable. Finally, save your changes and exit.
@ -111,14 +111,14 @@ In order to make use of Manim's interface to LaTeX to, for example, render
equations, LaTeX has to be installed as well. Note that this is an optional
dependency: if you don't intend to use LaTeX, you don't have to install it.
For Windows, the recommended LaTeX distribution is
For Windows, the recommended LaTeX distribution is
`MiKTeX <https://miktex.org/download>`__. You can install it by using the
installer from the linked MiKTeX site, or by using the package manager
of your choice (Chocolatey: ``choco install miktex.install``,
Scoop: ``scoop install latex``).
If you are concerned about disk space, there are some alternative,
smaller distributions of LaTeX like
smaller distributions of LaTeX like
`TinyTeX <https://yihui.org/tinytex/>`__ (Chocolatey: ``choco install tinytex``,
Scoop: first ``scoop bucket add r-bucket https://github.com/cderv/r-bucket.git``,
then ``scoop install tinytex``). In this case, you will have to manage the

View file

@ -133,7 +133,8 @@ class ManimDirective(Directive):
option_spec = {
"hide_source": bool,
"quality": lambda arg: directives.choice(
arg, ("low", "medium", "high", "fourk")
arg,
("low", "medium", "high", "fourk"),
),
"save_as_gif": bool,
"save_last_frame": bool,
@ -148,7 +149,9 @@ class ManimDirective(Directive):
if "skip-manim" in self.state.document.settings.env.app.builder.tags.tags:
node = skip_manim_node()
self.state.nested_parse(
StringList(self.content[0]), self.content_offset, node
StringList(self.content[0]),
self.content_offset,
node,
)
return [node]
@ -273,7 +276,8 @@ class ManimDirective(Directive):
ref_block=ref_block,
)
state_machine.insert_input(
rendered_template.split("\n"), source=document.attributes["source"]
rendered_template.split("\n"),
source=document.attributes["source"],
)
return []
@ -289,7 +293,7 @@ def _write_rendering_stats(scene_name, run_time, file_name):
re.sub(r"^(reference\/)|(manim\.)", "", file_name),
scene_name,
"%.3f" % run_time,
]
],
)
@ -312,7 +316,7 @@ def _log_rendering_times(*args):
continue
time_sum = sum(float(row[2]) for row in group)
print(
f"{key}{f'{time_sum:.3f}'.rjust(7, '.')}s => {len(group)} EXAMPLES"
f"{key}{f'{time_sum:.3f}'.rjust(7, '.')}s => {len(group)} EXAMPLES",
)
for row in group:
print(f"{' '*(max_file_length)} {row[2].rjust(7)}s {row[1]}")

View file

@ -8,7 +8,7 @@ Plugins are features that extend Manim's core functionality. Since Manim is
extensible and not everything belongs in its core, we'll go over how to
install, use, and create your own plugins.
.. note::
.. note::
The standard naming convention for plugins is to prefix the plugin with
``manim-``. This makes them easy for users to find on package
@ -65,7 +65,7 @@ For enabling a plugin ``manim.cfg`` or command line parameters should be used.
The plugins should be module name of the plugin and not PyPi name.
Enabling plugins through ``manim.cfg``
Enabling plugins through ``manim.cfg``
.. code-block:: ini

View file

@ -44,5 +44,3 @@ Module Index
~animation.transform
~animation.transform_matching_parts
~animation.update

View file

@ -12,5 +12,3 @@ Module Index
~_config
~_config.utils
~_config.logger_utils

View file

@ -77,4 +77,3 @@ Module Index
~mobject.types.image_mobject
~mobject.types.point_cloud_mobject
~mobject.types.vectorized_mobject

View file

@ -2,4 +2,4 @@ User-agent: *
Disallow: /
Allow: /en/stable/
Sitemap: https://docs.manim.community/sitemap.xml
Sitemap: https://docs.manim.community/sitemap.xml

View file

@ -274,7 +274,7 @@ the use of :meth:`.animate`.
self.play(square.animate.shift(UP).rotate(PI / 3))
self.wait(1)
:meth:`.animate` is a property of all mobjects that animates the methods that come
:meth:`.animate` is a property of all mobjects that animates the methods that come
afterward. For example, :code:`square.set_fill(WHITE)` sets the fill color of
the square, while :code:`sqaure.animate.set_fill(WHITE)` animates this action.
@ -368,7 +368,7 @@ Using coordinates of a mobject
==============================
Mobjects contain points that define their boundaries.
These points can be used to add other mobjects respectively to each other,
These points can be used to add other mobjects respectively to each other,
e.g. by methods like :meth:`~.Mobject.get_center` , :meth:`~.Mobject.get_top`
and :meth:`~.Mobject.get_start`. Here is an example of some important coordinates:
@ -411,12 +411,12 @@ It is also possible to transform a mobject into another mobject like this:
m2 = Rectangle().set_color(RED).rotate(0.2)
self.play(Transform(m1,m2))
The Transform function maps points of the previous mobject to the points of the
The Transform function maps points of the previous mobject to the points of the
next mobject.
This might result in strange behaviour, e.g. when the dots of one mobject are
This might result in strange behaviour, e.g. when the dots of one mobject are
arranged clockwise and the other points are arranged counterclockwise.
Here it might help to use the `flip` function and reposition the points via the
`roll <https://numpy.org/doc/stable/reference/generated/numpy.roll.html>`_
Here it might help to use the `flip` function and reposition the points via the
`roll <https://numpy.org/doc/stable/reference/generated/numpy.roll.html>`_
function of numpy:
.. manim:: ExampleRotation
@ -428,11 +428,11 @@ function of numpy:
m1b = Circle().set_color(RED).shift(LEFT)
m2a= Square().set_color(BLUE).shift(RIGHT)
m2b= Circle().set_color(BLUE).shift(RIGHT)
points = m2a.points
points = np.roll(points, int(len(points)/4), axis=0)
m2a.points = points
self.play(Transform(m1a,m1b),Transform(m2a,m2b), run_time=1)
******

View file

@ -90,7 +90,7 @@ high, and 4k quality, respectively.
.. code-block:: bash
manim -ql <file.py> SceneName
manim -ql <file.py> SceneName
These flags set the values of the config options ``config.pixel_width``,
``config.pixel_height``, ``config.frame_rate``, and ``config.quality``.
@ -110,7 +110,7 @@ instead of the whole video, you can execute
.. code-block:: bash
manim -sqh <file.py> SceneName
manim -sqh <file.py> SceneName
The following example specifies the output file name (with the :code:`-o`
flag), renders only the first ten animations (:code:`-n` flag) with a white
@ -120,7 +120,7 @@ open the file after it is rendered.
.. code-block:: bash
manim -o myscene -i -n 0,10 -c WHITE <file.py> SceneName
manim -o myscene -i -n 0,10 -c WHITE <file.py> SceneName
.. tip:: There are many more command-line flags that manim accepts. All the
possible flags are shown by executing ``manim render --help``. A complete list
@ -162,7 +162,7 @@ Now, executing the following command
.. code-block:: bash
manim -o myscene -i -c WHITE <file.py> SceneName
manim -o myscene -i -c WHITE <file.py> SceneName
is equivalent to executing the following command, provided that ``manim.cfg``
is in the same directory as <file.py>,
@ -377,8 +377,8 @@ A list of all CLI flags
plugins Manages Manim plugins.
Made with <3 by Manim Community developers.
Each of the subcommands has its own help page which can be
Each of the subcommands has its own help page which can be
.. code::

View file

@ -60,7 +60,7 @@ the following command:
.. code-block:: bash
manim -pql scene.py SquareToCircle
manim -pql scene.py SquareToCircle
After showing some output, manim should render the scene into a .mp4 file,
and open that file with the default movie player application. You should see a
@ -158,7 +158,7 @@ And render it using the following command:
.. code-block:: bash
manim -pql scene.py SquareToCircle
manim -pql scene.py SquareToCircle
The output should look as follows.

View file

@ -7,11 +7,11 @@ There are two different ways by which you can render **Text** in videos:
1. Using Pango (:mod:`~.text_mobject`)
2. Using LaTeX (:mod:`~.tex_mobject`)
If you want to render simple text, you should use either :class:`~.Text` or
If you want to render simple text, you should use either :class:`~.Text` or
:class:`~.MarkupText`, or one of its derivatives like :class:`~.Paragraph`.
See :ref:`using-text-objects` for more information.
LaTeX should be used when you need mathematical typesetting. See
LaTeX should be used when you need mathematical typesetting. See
:ref:`rendering-with-latex` for more information.
.. _using-text-objects:
@ -26,7 +26,7 @@ render non-English alphabets like 你好 or こんにちは or 안녕하세요
Here is a simple *Hello World* animation.
.. manim:: HelloWorld
.. manim:: HelloWorld
:save_last_frame:
:ref_classes: Text
@ -39,7 +39,7 @@ You can also use :class:`~.MarkupText` which allows the use of PangoMarkup
(see the documentation of :class:`~.MarkupText` for details) to render text.
For example:
.. manim:: SingleLineColor
.. manim:: SingleLineColor
:save_last_frame:
:ref_classes: MarkupText
@ -61,7 +61,7 @@ Using Fonts
You can set a different font using :attr:`~.Text.font`.
.. note::
.. note::
The font used must be installed in your system, and Pango should know
about it. You can get a list of fonts using :func:`manimpango.list_fonts`.
@ -71,9 +71,9 @@ You can set a different font using :attr:`~.Text.font`.
[...]
.. manim:: FontsExample
.. manim:: FontsExample
:save_last_frame:
class FontsExample(Scene):
def construct(self):
ft = Text("Noto Sans", font="Noto Sans")
@ -81,7 +81,7 @@ You can set a different font using :attr:`~.Text.font`.
Setting Slant and Weight
------------------------
Slant is the style of the Text, and it can be ``NORMAL`` (the default),
Slant is the style of the Text, and it can be ``NORMAL`` (the default),
``ITALIC`` or ``OBLIQUE``. Usually, for many fonts both ``ITALIC`` and
``OBLIQUE`` look similar, but ``ITALIC`` uses **Roman Style**, whereas
``OBLIQUE`` uses **Italic Style**.
@ -97,7 +97,7 @@ Weight specifies the boldness of a font. You can see a list of weights in
a = Text("Italic", slant=ITALIC)
self.add(a)
.. manim:: DifferentWeight
.. manim:: DifferentWeight
:save_last_frame:
class DifferentWeight(Scene):
@ -131,10 +131,10 @@ as explained in :ref:`iterating-text`.
:attr:`~Text.t2c` accepts two types of dictionaries,
* The keys can contain indices like ``[2:-1]`` or ``[4:8]``,
* The keys can contain indices like ``[2:-1]`` or ``[4:8]``,
this works similar to how `slicing <https://realpython.com/python-strings/#string-slicing>`_
works in Python. The values should be the color of the Text from :class:`~.Color`.
* The keys contain words or characters which should be colored separately
and the values should be the color from :class:`~.Color`:
@ -166,7 +166,7 @@ be an iterable of any length:
t = Text("Hello", gradient=(RED, BLUE, GREEN), font_size=96)
self.add(t)
You can also use :attr:`~.Text.t2g` for gradients with specific
You can also use :attr:`~.Text.t2g` for gradients with specific
characters of the text. It shares a similar syntax to :ref:`the
interface for colors <using-colors>`:
@ -210,7 +210,7 @@ Disabling Ligatures
-------------------
By disabling ligatures you would get a one-to-one mapping between characters and
submobjects. This fixes the issues with coloring text.
submobjects. This fixes the issues with coloring text.
.. warning::
@ -218,7 +218,7 @@ submobjects. This fixes the issues with coloring text.
Be aware that using this method with text that heavily depends on
ligatures (Arabic text) may yield unexpected results.
You can disable ligatures by passing ``disable_ligatures`` to
You can disable ligatures by passing ``disable_ligatures`` to
:class:`Text`. For example:
.. manim:: DisableLigature
@ -262,14 +262,14 @@ For example, you can set each letter to different color by iterating it.
Working with :class:`~.MarkupText`
==================================
MarkupText is similar to :class:`~.Text`, the only difference between them is
MarkupText is similar to :class:`~.Text`, the only difference between them is
that this accepts and processes PangoMarkup (which is similar to
html), instead of just rendering plain text.
Consult the documentation of :class:`~.MarkupText` for more details
and further references about PangoMarkup.
.. manim:: MarkupTest
.. manim:: MarkupTest
:save_last_frame:
class MarkupTest(Scene):
@ -291,7 +291,7 @@ use :class:`~.Tex` to insert LaTeX.
For example,
.. manim:: HelloLaTeX
.. manim:: HelloLaTeX
:save_last_frame:
class HelloLaTeX(Scene):
@ -314,14 +314,14 @@ Everything passed to :class:`~.MathTex` is in math mode by default. To be more p
similar effect with :class:`~.Tex` by enclosing your formula with ``$`` symbols:
``$\xrightarrow{x^6y^8}$``:
.. manim:: MathTeXDemo
.. manim:: MathTeXDemo
:save_last_frame:
class MathTeXDemo(Scene):
def construct(self):
rtarrow0 = MathTex(r"\xrightarrow{x^6y^8}", font_size=96)
rtarrow1 = Tex(r"$\xrightarrow{x^6y^8}$", font_size=96)
self.add(VGroup(rtarrow0, rtarrow1).arrange(DOWN))
@ -339,8 +339,8 @@ as the ``mathtt`` math-text type or the ``looparrowright`` arrow.
tex = Tex(r'$\mathtt{H} \looparrowright$ \LaTeX', font_size=144)
self.add(tex)
On the Manim side, the :class:`~.Tex` class also accepts attributes to
change the appearance of the output. This is very similar to the
On the Manim side, the :class:`~.Tex` class also accepts attributes to
change the appearance of the output. This is very similar to the
:class:`~.Text` class. For example, the ``color`` keyword changes the
color of the TeX mobject.
@ -355,7 +355,7 @@ color of the TeX mobject.
Extra LaTeX Packages
====================
Some commands require special packages to be loaded into the TeX template.
Some commands require special packages to be loaded into the TeX template.
For example, to use the ``mathscr`` script, we need to add the ``mathrsfs``
package. Since this package isn't loaded into Manim's tex template by default,
we have to add it manually.
@ -401,7 +401,7 @@ the Tex, not just the specific symbol or Tex expression. Consider the following
equation.set_color_by_tex("x", YELLOW)
self.add(equation)
As you can see, this colors the entire equation yellow, contrary to what
As you can see, this colors the entire equation yellow, contrary to what
may be expected. To color only ``x`` yellow, we have to do the following:
.. manim:: CorrectLaTeXSubstringColoring
@ -417,8 +417,8 @@ may be expected. To color only ``x`` yellow, we have to do the following:
self.add(equation)
By setting ``substrings_to_isolate`` to ``x``, we split up the
:class:`~.MathTex` into substrings automatically and isolate the ``x`` components
into individual substrings. Only then can :meth:`~.set_color_by_tex` be used
:class:`~.MathTex` into substrings automatically and isolate the ``x`` components
into individual substrings. Only then can :meth:`~.set_color_by_tex` be used
to achieve the desired result.
Note that Manim also supports a custom syntax that allows splitting
@ -432,9 +432,9 @@ to write using :class:`~.TransformMatchingTex`.
LaTeX Maths Fonts - The Template Library
========================================
Changing fonts in LaTeX when typesetting mathematical formulae is
Changing fonts in LaTeX when typesetting mathematical formulae is
trickier than regular text. It requires changing the template that is used
to compile the TeX. Manim comes with a collection of :class:`~.TexFontTemplates`
to compile the TeX. Manim comes with a collection of :class:`~.TexFontTemplates`
ready for you to use. These templates will all work in math mode:
.. manim:: LaTeXMathFonts
@ -445,11 +445,11 @@ ready for you to use. These templates will all work in math mode:
tex = Tex(r'$x^2 + y^2 = z^2$', tex_template=TexFontTemplates.french_cursive, font_size=144)
self.add(tex)
Manim also has a :class:`~.TexTemplateLibrary` containing the TeX
Manim also has a :class:`~.TexTemplateLibrary` containing the TeX
templates used by 3Blue1Brown. One example is the ctex template,
used for typesetting Chinese script. For this to work, the ctex LaTeX package
must be installed on your system. Furthermore, if you are only
typesetting Text, you probably do not need :class:`~.Tex` at all, and
must be installed on your system. Furthermore, if you are only
typesetting Text, you probably do not need :class:`~.Tex` at all, and
should use :class:`~.Text` instead.
.. manim:: LaTeXTemplateLibrary
@ -465,7 +465,7 @@ Aligning formulae
=================
:class:`~.MathTex` mobject is typeset in the LaTeX ``align*``
environment. This means you can use the ``&`` alignment character
environment. This means you can use the ``&`` alignment character
when typesetting multiline formulae:
.. manim:: LaTeXAlignEnvironment

View file

@ -13,7 +13,7 @@ TemplateForFrenchCursive = TexTemplate(
\usepackage[default]{frcursive}
\usepackage[eulergreek,noplusnominus,noequal,nohbar,%
nolessnomore,noasterisk]{mathastext}
"""
""",
)
@ -33,9 +33,9 @@ class TexFontTemplateManual(Scene):
self.play(
Create(
Tex(
"See more font templates at \\\\ http://jf.burnol.free.fr/showcase.html"
).shift(2 * DOWN)
)
"See more font templates at \\\\ http://jf.burnol.free.fr/showcase.html",
).shift(2 * DOWN),
),
)
self.wait(2)
@ -132,8 +132,8 @@ class TexFontTemplateLibrary(Scene):
self.play(
Create(
Tex(
"See more font templates at \\\\ http://jf.burnol.free.fr/showcase.html"
).shift(2 * DOWN)
)
"See more font templates at \\\\ http://jf.burnol.free.fr/showcase.html",
).shift(2 * DOWN),
),
)
self.wait(2)

View file

@ -46,7 +46,7 @@ class OpeningManim(Scene):
self.wait()
grid_transform_title = Tex(
r"That was a non-linear function \\ applied to the grid"
r"That was a non-linear function \\ applied to the grid",
)
grid_transform_title.move_to(grid_title, UL)
grid.prepare_for_nonlinear_transform()
@ -58,8 +58,8 @@ class OpeningManim(Scene):
np.sin(p[1]),
np.sin(p[0]),
0,
]
)
],
),
),
run_time=3,
)
@ -86,8 +86,9 @@ class WarpSquare(Scene):
square = Square()
self.play(
ApplyPointwiseFunction(
lambda point: complex_to_R3(np.exp(R3_to_complex(point))), square
)
lambda point: complex_to_R3(np.exp(R3_to_complex(point))),
square,
),
)
self.wait()

View file

@ -8,8 +8,7 @@ logging_level_info = dim green
logging_level_warning = dim red
logging_level_error = red
logging_level_critical = red
log_level =
log_level =
log_time = dim yellow
log_message = green
log_path = dim

View file

@ -41,7 +41,7 @@ def get_plane_mesh(context):
[-1, 0, -1, 1],
[1, 0, -1, 1],
[1, 0, 1, 1],
]
],
)
attributes["in_color"] = np.array(
[
@ -66,7 +66,7 @@ def get_plane_mesh(context):
[0, 0, 1, 1],
[0, 0, 1, 1],
[0, 0, 1, 1],
]
],
)
return Mesh(shader, attributes)
@ -95,7 +95,8 @@ class GuiTest(Scene):
def update_mesh(mesh, dt):
mesh.model_matrix = np.matmul(
opengl.rotation_matrix(z=dt), mesh.model_matrix
opengl.rotation_matrix(z=dt),
mesh.model_matrix,
)
mesh.add_updater(update_mesh)
@ -124,7 +125,7 @@ class GuiTest2(Scene):
"min_value": 0,
"max_value": 1,
"default_value": 1,
}
},
)
self.interactive_embed()
@ -145,7 +146,8 @@ class ThreeDMobjectTest(Scene):
def update_mesh(mesh, dt):
mesh.model_matrix = np.matmul(
opengl.rotation_matrix(z=dt), mesh.model_matrix
opengl.rotation_matrix(z=dt),
mesh.model_matrix,
)
mesh.add_updater(update_mesh)
@ -157,7 +159,8 @@ class NamedFullScreenQuad(Scene):
def construct(self):
surface = FullScreenQuad(self.renderer.context, fragment_shader_name="design_3")
surface.shader.set_uniform(
"u_resolution", (config["pixel_width"], config["pixel_height"], 0.0)
"u_resolution",
(config["pixel_width"], config["pixel_height"], 0.0),
)
surface.shader.set_uniform("u_time", 0)
self.add(surface)
@ -219,7 +222,8 @@ class InlineFullScreenQuad(Scene):
""",
)
surface.shader.set_uniform(
"u_resolution", (config["pixel_width"], config["pixel_height"])
"u_resolution",
(config["pixel_width"], config["pixel_height"]),
)
shader_time = 0
@ -322,7 +326,8 @@ class InlineShaderExample(Scene):
)
shader.set_uniform("u_model_view_matrix", opengl.view_matrix())
shader.set_uniform(
"u_projection_matrix", opengl.orthographic_projection_matrix()
"u_projection_matrix",
opengl.orthographic_projection_matrix(),
)
attributes = np.zeros(
@ -340,7 +345,7 @@ class InlineShaderExample(Scene):
[-1, -1, 0, 1],
[1, -1, 0, 1],
[1, 1, 0, 1],
]
],
)
attributes["in_color"] = np.array(
[
@ -350,7 +355,7 @@ class InlineShaderExample(Scene):
[0, 0, 1, 1],
[0, 0, 1, 1],
[0, 0, 1, 1],
]
],
)
mesh = Mesh(shader, attributes)
self.add(mesh)
@ -367,7 +372,8 @@ class NamedShaderExample(Scene):
view_matrix = self.camera.get_view_matrix()
shader.set_uniform("u_model_view_matrix", view_matrix)
shader.set_uniform(
"u_projection_matrix", opengl.perspective_projection_matrix()
"u_projection_matrix",
opengl.perspective_projection_matrix(),
)
attributes = np.zeros(
6,
@ -383,7 +389,7 @@ class NamedShaderExample(Scene):
[-1, -1, 0, 1],
[1, -1, 0, 1],
[1, 1, 0, 1],
]
],
)
mesh = Mesh(shader, attributes)
self.add(mesh)

View file

@ -1,6 +1,5 @@
#!/usr/bin/env python
# flake8: noqa
import pkg_resources

View file

@ -23,7 +23,8 @@ parser = make_config_parser()
# Throughout the codebase, use manim.console.print() instead of print().
# Use error_console to print errors so that it outputs to stderr.
logger, console, error_console = make_logger(
parser["logger"], parser["CLI"]["verbosity"]
parser["logger"],
parser["CLI"]["verbosity"],
)
# TODO: temporary to have a clean terminal output when working with PIL or matplotlib
logging.getLogger("PIL").setLevel(logging.INFO)

View file

@ -116,7 +116,7 @@ fullscreen = False
window_position = UR
# Manually adjust the size of the window, or use default to automatically scale the window based on
# the dimensions of the monitor.
# the dimensions of the monitor.
# --window_size
window_size = default
@ -150,7 +150,7 @@ tex_template =
# specify the plugins as comma separated values
# manim will load that plugin if it specified here.
plugins =
plugins =
# Overrides the default output folders, NOT the output file names. Note that
# if the custom_folders flag is present, the Tex and text files will not be put

View file

@ -49,7 +49,8 @@ Loading the default color configuration.[/logging.level.error]
def make_logger(
parser: configparser.ConfigParser, verbosity: str
parser: configparser.ConfigParser,
verbosity: str,
) -> typing.Tuple[logging.Logger, Console]:
"""Make the manim logger and console.
@ -88,7 +89,8 @@ def make_logger(
# set the rich handler
RichHandler.KEYWORDS = HIGHLIGHTED_KEYWORDS
rich_handler = RichHandler(
console=console, show_time=parser.getboolean("log_timestamps")
console=console,
show_time=parser.getboolean("log_timestamps"),
)
# finally, the logger
@ -130,7 +132,7 @@ def parse_theme(parser: configparser.ConfigParser) -> Theme:
k: v
for k, v in theme.items()
if k not in ["log.width", "log.height", "log.timestamps"]
}
},
)
except (color.ColorParseError, errors.StyleSyntaxError):
printf(WRONG_COLOR_CONFIG_MSG)
@ -201,5 +203,5 @@ class JSONFormatter(logging.Formatter):
"levelname": record_c.levelname,
"module": record_c.module,
"message": super().format(record_c),
}
},
)

View file

@ -445,18 +445,18 @@ class ManimConfig(MutableMapping):
self._d[key] = val
else:
raise ValueError(
f"{key} must be an integer such that {lo} <= {key} <= {hi}"
f"{key} must be an integer such that {lo} <= {key} <= {hi}",
)
def _set_pos_number(self, key: str, val: int, allow_inf: bool) -> None:
"""Set ``key`` to ``val`` if ``val`` is a positive integer."""
if isinstance(val, int) and val > -1:
self._d[key] = val
elif allow_inf and (val == -1 or val == float("inf")):
elif allow_inf and val in [-1, float("inf")]:
self._d[key] = float("inf")
else:
raise ValueError(
f"{key} must be a non-negative integer (use -1 for infinity)"
f"{key} must be a non-negative integer (use -1 for infinity)",
)
def __repr__(self) -> str:
@ -696,9 +696,8 @@ class ManimConfig(MutableMapping):
self[key] = attr
# dry_run is special because it can only be set to True
if hasattr(args, "dry_run"):
if getattr(args, "dry_run"):
self["dry_run"] = True
if getattr(args, "dry_run", False):
self["dry_run"] = True
for key in [
"media_dir", # always set this one first
@ -723,7 +722,7 @@ class ManimConfig(MutableMapping):
self.upto_animation_number = nflag[1]
except Exception:
logging.getLogger("manim").info(
f"No end scene number specified in -n option. Rendering from {nflag[0]} onwards..."
f"No end scene number specified in -n option. Rendering from {nflag[0]} onwards...",
)
# Handle the quality flags
@ -759,10 +758,9 @@ class ManimConfig(MutableMapping):
if args.tex_template:
self.tex_template = TexTemplateFromFile(tex_filename=args.tex_template)
if self.renderer == "opengl":
if getattr(args, "write_to_movie") is None:
# --write_to_movie was not passed on the command line, so don't generate video.
self["write_to_movie"] = False
if self.renderer == "opengl" and getattr(args, "write_to_movie") is None:
# --write_to_movie was not passed on the command line, so don't generate video.
self["write_to_movie"] = False
# Handle --gui_location flag.
if getattr(args, "gui_location") is not None:
@ -827,7 +825,9 @@ class ManimConfig(MutableMapping):
progress_bar = property(
lambda self: self._d["progress_bar"],
lambda self, val: self._set_from_list(
"progress_bar", val, ["none", "display", "leave"]
"progress_bar",
val,
["none", "display", "leave"],
),
doc="Whether to show progress bars while rendering animations.",
)
@ -912,13 +912,15 @@ class ManimConfig(MutableMapping):
)
if self.format == "webm":
logging.getLogger("manim").warning(
"Output format set as webm, this can be slower than other formats"
"Output format set as webm, this can be slower than other formats",
)
ffmpeg_loglevel = property(
lambda self: self._d["ffmpeg_loglevel"],
lambda self, val: self._set_from_list(
"ffmpeg_loglevel", val, ["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"]
"ffmpeg_loglevel",
val,
["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"],
),
doc="Verbosity level of ffmpeg (no flag).",
)
@ -1052,7 +1054,9 @@ class ManimConfig(MutableMapping):
movie_file_extension = property(
lambda self: self._d["movie_file_extension"],
lambda self, val: self._set_from_list(
"movie_file_extension", val, [".mp4", ".mov", ".webm"]
"movie_file_extension",
val,
[".mp4", ".mov", ".webm"],
),
doc="Either .mp4, .webm or .mov.",
)
@ -1125,7 +1129,7 @@ class ManimConfig(MutableMapping):
"It is unclear what it means to set dry_run to "
"False. Instead, try setting each option "
"individually. (write_to_movie, write_all, "
"save_last_frame, save_pngs, or save_as_gif)"
"save_last_frame, save_pngs, or save_as_gif)",
)
@property
@ -1401,7 +1405,7 @@ class ManimConfig(MutableMapping):
raise KeyError(
"must pass one of "
"{media,video,images,text,tex,log}_dir "
"or {input,output}_file"
"or {input,output}_file",
)
dirs.remove(key) # a path cannot contain itself
@ -1418,7 +1422,7 @@ class ManimConfig(MutableMapping):
raise KeyError(
f"{key} {self._d[key]} requires the following "
+ "keyword arguments: "
+ " ".join(exc.args)
+ " ".join(exc.args),
) from exc
return Path(path) if path else None
@ -1520,7 +1524,7 @@ class ManimConfig(MutableMapping):
if val:
if not os.access(val, os.R_OK):
logging.getLogger("manim").warning(
f"Custom TeX template {val} not found or not readable."
f"Custom TeX template {val} not found or not readable.",
)
else:
self._d["tex_template_file"] = Path(val)

View file

@ -108,7 +108,7 @@ class Animation:
logger.debug(
f"The {cls.__name__} animation has been is overridden for "
f"{type(mobject).__name__} mobjects. use_override = False can "
f" be used as keyword argument to prevent animation overriding."
f" be used as keyword argument to prevent animation overriding.",
)
return anim
return super().__new__(cls)
@ -141,7 +141,7 @@ class Animation:
(
"CONFIG has been removed from ManimCommunity.",
"Please use keyword arguments instead.",
)
),
)
def _typecheck_input(self, mobject: Union[Mobject, None]) -> None:
@ -418,7 +418,7 @@ class Animation:
def prepare_animation(
anim: Union["Animation", "mobject._AnimationBuilder"]
anim: Union["Animation", "mobject._AnimationBuilder"],
) -> "Animation":
r"""Returns either an unchanged animation, or the animation built
from a passed animation factory.

View file

@ -37,7 +37,7 @@ class AnimationGroup(Animation):
self.group = group
if self.group is None:
mobjects = remove_list_redundancies(
[anim.mobject for anim in self.animations]
[anim.mobject for anim in self.animations],
)
if config["renderer"] == "opengl":
self.group = OpenGLGroup(*mobjects)

View file

@ -121,7 +121,10 @@ class ShowPartial(Animation):
super().__init__(mobject, **kwargs)
def interpolate_submobject(
self, submobject: Mobject, starting_submobject: Mobject, alpha: float
self,
submobject: Mobject,
starting_submobject: Mobject,
alpha: float,
) -> None:
submobject.pointwise_become_partial(
starting_submobject, *self._get_bounds(alpha)
@ -254,7 +257,11 @@ class DrawBorderThenFill(Animation):
return [*super().get_all_mobjects(), self.outline]
def interpolate_submobject(
self, submobject: Mobject, starting_submobject: Mobject, outline, alpha: float
self,
submobject: Mobject,
starting_submobject: Mobject,
outline,
alpha: float,
) -> None: # Fixme: not matching the parent class? What is outline doing here?
index: int
subalpha: int
@ -294,7 +301,9 @@ class Write(DrawBorderThenFill):
run_time: Optional[float] = kwargs.pop("run_time", None)
lag_ratio: Optional[float] = kwargs.pop("lag_ratio", None)
run_time, lag_ratio = self._set_default_config_from_length(
vmobject, run_time, lag_ratio
vmobject,
run_time,
lag_ratio,
)
self.reverse = reverse
super().__init__(
@ -374,7 +383,9 @@ class Unwrite(Write):
run_time: Optional[float] = kwargs.pop("run_time", None)
lag_ratio: Optional[float] = kwargs.pop("lag_ratio", None)
run_time, lag_ratio = self._set_default_config_from_length(
vmobject, run_time, lag_ratio
vmobject,
run_time,
lag_ratio,
)
super().__init__(
vmobject,

View file

@ -464,7 +464,10 @@ class ApplyWave(Homotopy):
return (1 - 2 * wave_func(t * ripples)) * (1 - 2 * ((phase) % 2))
def homotopy(
x: float, y: float, z: float, t: float
x: float,
y: float,
z: float,
t: float,
) -> Tuple[float, float, float]:
upper = interpolate(0, 1 + time_width, t)
lower = upper - time_width
@ -536,7 +539,10 @@ class Wiggle(Animation):
return self.mobject.get_center()
def interpolate_submobject(
self, submobject: "Mobject", starting_submobject: "Mobject", alpha: float
self,
submobject: "Mobject",
starting_submobject: "Mobject",
alpha: float,
) -> None:
submobject.points[:, :] = starting_submobject.points
submobject.scale(
@ -606,11 +612,15 @@ class Circumscribe(Succession):
):
if shape is Rectangle:
frame = SurroundingRectangle(
mobject, color, buff, stroke_width=stroke_width
mobject,
color,
buff,
stroke_width=stroke_width,
)
elif shape is Circle:
frame = Circle(color=color, stroke_width=stroke_width).surround(
mobject, buffer_factor=1
mobject,
buffer_factor=1,
)
radius = frame.width / 2
frame.scale((radius + buff) / radius)

View file

@ -42,7 +42,10 @@ class Homotopy(Animation):
return lambda p: self.homotopy(*p, t)
def interpolate_submobject(
self, submobject: "Mobject", starting_submobject: "Mobject", alpha: float
self,
submobject: "Mobject",
starting_submobject: "Mobject",
alpha: float,
) -> None:
submobject.points = starting_submobject.points
submobject.apply_function(
@ -52,7 +55,10 @@ class Homotopy(Animation):
class SmoothedVectorizedHomotopy(Homotopy):
def interpolate_submobject(
self, submobject: "Mobject", starting_submobject: "Mobject", alpha: float
self,
submobject: "Mobject",
starting_submobject: "Mobject",
alpha: float,
) -> None:
Homotopy.interpolate_submobject(self, submobject, starting_submobject, alpha)
submobject.make_smooth()
@ -67,7 +73,10 @@ class ComplexHomotopy(Homotopy):
"""
def homotopy(
x: float, y: float, z: float, t: float
x: float,
y: float,
z: float,
t: float,
) -> Tuple[float, float, float]:
c = complex_homotopy(complex(x, y), t)
return (c.real, c.imag, z)

View file

@ -83,7 +83,8 @@ class Transform(Animation):
def path_func(
self,
) -> Callable[
[Iterable[np.ndarray], Iterable[np.ndarray], float], Iterable[np.ndarray]
[Iterable[np.ndarray], Iterable[np.ndarray], float],
Iterable[np.ndarray],
]:
return self._path_func
@ -91,7 +92,8 @@ class Transform(Animation):
def path_func(
self,
path_func: Callable[
[Iterable[np.ndarray], Iterable[np.ndarray], float], Iterable[np.ndarray]
[Iterable[np.ndarray], Iterable[np.ndarray], float],
Iterable[np.ndarray],
],
) -> None:
if path_func is not None:
@ -245,7 +247,7 @@ class MoveToTarget(Transform):
def check_validity_of_input(self, mobject: Mobject) -> None:
if not hasattr(mobject, "target"):
raise ValueError(
"MoveToTarget called on mobject" "without attribute 'target'"
"MoveToTarget called on mobject" "without attribute 'target'",
)
@ -276,7 +278,7 @@ class ApplyMethod(Transform):
if not inspect.ismethod(method):
raise ValueError(
"Whoops, looks like you accidentally invoked "
"the method you want to animate"
"the method you want to animate",
)
assert isinstance(method.__self__, (Mobject, OpenGLMobject))
@ -364,7 +366,7 @@ class ApplyFunction(Transform):
target = self.function(self.mobject.copy())
if not isinstance(target, (Mobject, OpenGLMobject)):
raise TypeError(
"Functions passed to ApplyFunction must return object of type Mobject"
"Functions passed to ApplyFunction must return object of type Mobject",
)
return target

View file

@ -111,7 +111,7 @@ class TransformMatchingAbstractBase(AnimationGroup):
target_map.pop(key2, None)
if len(key_mapped_source) > 0:
anims.append(
FadeTransformPieces(key_mapped_source, key_mapped_target, **kwargs)
FadeTransformPieces(key_mapped_source, key_mapped_target, **kwargs),
)
fade_source = group_type()
@ -130,7 +130,7 @@ class TransformMatchingAbstractBase(AnimationGroup):
else:
anims.append(FadeOut(fade_source, target_position=fade_target, **kwargs))
anims.append(
FadeIn(fade_target.copy(), target_position=fade_target, **kwargs)
FadeIn(fade_target.copy(), target_position=fade_target, **kwargs),
)
super().__init__(*anims)

View file

@ -249,10 +249,12 @@ class Camera:
self.background = self.background.astype(self.pixel_array_dtype)
else:
background_rgba = color_to_int_rgba(
self.background_color, self.background_opacity
self.background_color,
self.background_opacity,
)
self.background = np.zeros(
(height, width, self.n_channels), dtype=self.pixel_array_dtype
(height, width, self.n_channels),
dtype=self.pixel_array_dtype,
)
self.background[:, :] = background_rgba
@ -345,6 +347,7 @@ class Camera:
coords_to_colors_func : function
The function whose input is an (x,y) pair of coordinates and
whose return values must be the colors for that point
Returns
-------
np.array
@ -396,7 +399,10 @@ class Camera:
####
def get_mobjects_to_display(
self, mobjects, include_submobjects=True, excluded_mobjects=None
self,
mobjects,
include_submobjects=True,
excluded_mobjects=None,
):
"""Used to get the list of mobjects to display
with the camera.
@ -417,11 +423,14 @@ class Camera:
"""
if include_submobjects:
mobjects = extract_mobject_family_members(
mobjects, use_z_index=self.use_z_index, only_those_with_points=True
mobjects,
use_z_index=self.use_z_index,
only_those_with_points=True,
)
if excluded_mobjects:
all_excluded = extract_mobject_family_members(
excluded_mobjects, use_z_index=self.use_z_index
excluded_mobjects,
use_z_index=self.use_z_index,
)
mobjects = list_difference_update(mobjects, all_excluded)
return mobjects
@ -546,7 +555,10 @@ class Camera:
fh = self.frame_height
fc = self.frame_center
surface = cairo.ImageSurface.create_for_data(
pixel_array, cairo.FORMAT_ARGB32, pw, ph
pixel_array,
cairo.FORMAT_ARGB32,
pw,
ph,
)
ctx = cairo.Context(surface)
ctx.scale(pw, ph)
@ -558,7 +570,7 @@ class Camera:
-fdiv(ph, fh),
(pw / 2) - fc[0] * fdiv(pw, fw),
(ph / 2) + fc[1] * fdiv(ph, fh),
)
),
)
self.cache_cairo_context(pixel_array, ctx)
return ctx
@ -581,7 +593,8 @@ class Camera:
self.display_multiple_background_colored_vmobjects(batch, pixel_array)
else:
self.display_multiple_non_background_colored_vmobjects(
batch, pixel_array
batch,
pixel_array,
)
def display_multiple_non_background_colored_vmobjects(self, vmobjects, pixel_array):
@ -648,7 +661,7 @@ class Camera:
ctx.new_sub_path()
start = subpath[0]
ctx.move_to(*start[:2])
for p0, p1, p2, p3 in quads:
for _p0, p1, p2, p3 in quads:
ctx.curve_to(*p1[:2], *p2[:2], *p3[:2])
if vmobject.consider_points_equals_2d(subpath[0], subpath[-1]):
ctx.close_path()
@ -727,13 +740,15 @@ class Camera:
if width == 0:
return self
self.set_cairo_context_color(
ctx, self.get_stroke_rgbas(vmobject, background=background), vmobject
ctx,
self.get_stroke_rgbas(vmobject, background=background),
vmobject,
)
ctx.set_line_width(
width
* self.cairo_line_width_multiple
# This ensures lines have constant width as you zoom in on them.
* (self.frame_width / self.frame_width)
* (self.frame_width / self.frame_width),
)
ctx.stroke_preserve()
return self
@ -847,6 +862,7 @@ class Camera:
The thickness of each point of the PMobject
pixel_array : np.array
The pixel array to modify.
"""
if len(points) == 0:
return
@ -910,7 +926,8 @@ class Camera:
pixel_width = max(int(pdist([ul_coords, ur_coords])), 1)
pixel_height = max(int(pdist([ul_coords, dl_coords])), 1)
sub_image = sub_image.resize(
(pixel_width, pixel_height), resample=image_mobject.resampling_algorithm
(pixel_width, pixel_height),
resample=image_mobject.resampling_algorithm,
)
# Rotate
@ -918,14 +935,17 @@ class Camera:
adjusted_angle = -int(360 * angle / TAU)
if adjusted_angle != 0:
sub_image = sub_image.rotate(
adjusted_angle, resample=image_mobject.resampling_algorithm, expand=1
adjusted_angle,
resample=image_mobject.resampling_algorithm,
expand=1,
)
# TODO, there is no accounting for a shear...
# Paste into an image as large as the camera's pixel array
full_image = Image.fromarray(
np.zeros((self.pixel_height, self.pixel_width)), mode="RGBA"
np.zeros((self.pixel_height, self.pixel_width)),
mode="RGBA",
)
new_ul_coords = center_coords - np.array(sub_image.size) / 2
new_ul_coords = new_ul_coords.astype(int)
@ -964,7 +984,8 @@ class Camera:
The Image to overlay.
"""
pixel_array[:, :] = np.array(
Image.alpha_composite(self.get_image(pixel_array), image), dtype="uint8"
Image.alpha_composite(self.get_image(pixel_array), image),
dtype="uint8",
)
def adjust_out_of_range_points(self, points):
@ -988,14 +1009,18 @@ class Camera:
violators = points[violator_indices, :]
violator_norms = norms[violator_indices]
reshaped_norms = np.repeat(
violator_norms.reshape((len(violator_norms), 1)), points.shape[1], 1
violator_norms.reshape((len(violator_norms), 1)),
points.shape[1],
1,
)
rescaled = self.max_allowable_norm * violators / reshaped_norms
points[violator_indices] = rescaled
return points
def transform_points_pre_display(
self, mobject, points
self,
mobject,
points,
): # TODO: Write more detailed docstrings for this method.
# NOTE: There seems to be an unused argument `mobject`.
@ -1008,7 +1033,9 @@ class Camera:
return points
def points_to_pixel_coords(
self, mobject, points
self,
mobject,
points,
): # TODO: Write more detailed docstrings for this method.
points = self.transform_points_pre_display(mobject, points)
shifted_points = points - self.frame_center
@ -1127,7 +1154,8 @@ class Camera:
::-1
].transpose(1, 2, 0)
uncentered_space_coords = fdiv(
uncentered_pixel_coords * full_space_dims, full_pixel_dims
uncentered_pixel_coords * full_space_dims,
full_pixel_dims,
)
# Could structure above line's computation slightly differently, but figured (without much
# thought) multiplying by frame_shape first, THEN dividing by pixel_shape, is probably
@ -1162,7 +1190,11 @@ class BackgroundColoredVMobjectDisplayer:
self.pixel_array[:, :] = 0
def resize_background_array(
self, background_array, new_width, new_height, mode="RGBA"
self,
background_array,
new_width,
new_height,
mode="RGBA",
):
"""Resizes the pixel array representing the background.
@ -1254,7 +1286,8 @@ class BackgroundColoredVMobjectDisplayer:
background_array = self.get_background_array(image)
pixel_array = self.pixel_array
self.camera.display_multiple_non_background_colored_vmobjects(
batch, pixel_array
batch,
pixel_array,
)
new_array = np.array(
(background_array * pixel_array.astype("float") / 255),

View file

@ -32,7 +32,8 @@ class MappingCamera(Camera):
def points_to_pixel_coords(self, points):
return Camera.points_to_pixel_coords(
self, np.apply_along_axis(self.mapping_func, 1, points)
self,
np.apply_along_axis(self.mapping_func, 1, points),
)
def capture_mobjects(self, mobjects, **kwargs):
@ -74,7 +75,7 @@ class OldMultiCamera(Camera):
+ camera_with_start_positions[0].pixel_width,
"end_y": camera_with_start_positions[1][0]
+ camera_with_start_positions[0].pixel_height,
}
},
)
for camera_with_start_positions in cameras_with_start_positions
]

View file

@ -121,7 +121,9 @@ class ThreeDCamera(Camera):
return rgbas
def get_stroke_rgbas(
self, vmobject, background=False
self,
vmobject,
background=False,
): # NOTE : DocStrings From parent
return self.modified_rgbas(vmobject, vmobject.get_stroke_rgbas(background))
@ -333,7 +335,9 @@ class ThreeDCamera(Camera):
return self.project_points(point.reshape((1, 3)))[0, :]
def transform_points_pre_display(
self, mobject, points
self,
mobject,
points,
): # TODO: Write Docstrings for this Method.
points = super().transform_points_pre_display(mobject, points)
fixed_orientation = mobject in self.fixed_orientation_mobjects

View file

@ -23,7 +23,7 @@ class WebGLCamera(Camera):
"style": vmobject.get_style(simple=True),
"id": id(vmobject),
"needs_redraw": needs_redraw,
}
},
)
def reset(self):

View file

@ -138,7 +138,8 @@ def cfg(ctx):
def write(level: str = None, openfile: bool = False) -> None:
config_paths = config_file_paths()
console.print(
"[yellow bold]Manim Configuration File Writer[/yellow bold]", justify="center"
"[yellow bold]Manim Configuration File Writer[/yellow bold]",
justify="center",
)
USER_CONFIG_MSG = f"""A configuration file at [yellow]{config_paths[1]}[/yellow] has been created with your required changes.
@ -182,17 +183,21 @@ To save your config please save that file and place it in your current working d
raise Exception(
"""Not enough values in input.
You may have added a new entry to default.cfg, in which case you will have to
modify write_cfg_subcmd_input to account for it."""
modify write_cfg_subcmd_input to account for it.""",
)
if temp:
while temp and not _is_expected_datatype(
temp, default[key], bool(style)
temp,
default[key],
bool(style),
):
console.print(
f"[red bold]Invalid {desc}. Try again.[/red bold]"
f"[red bold]Invalid {desc}. Try again.[/red bold]",
)
console.print(
f"Enter the {desc} for {key}:", style=style, end=""
f"Enter the {desc} for {key}:",
style=style,
end="",
)
temp = input()
else:
@ -259,7 +264,7 @@ Are you sure you want to continue? (y/n)""",
style="red bold",
end="",
)
proceed = True if input().lower() == "y" else False
proceed = input().lower() == "y"
else:
proceed = True
if proceed:

View file

@ -32,7 +32,7 @@ def select_resolution():
resolution_options = []
for quality in QUALITIES.items():
resolution_options.append(
(quality[1]["pixel_height"], quality[1]["pixel_width"])
(quality[1]["pixel_height"], quality[1]["pixel_width"]),
)
resolution_options.pop()
choice = click.prompt(
@ -100,7 +100,7 @@ def project(default_settings, **args):
if project_name.is_dir():
console.print(
f"\nFolder [red]{project_name}[/red] exists. Please type another name\n"
f"\nFolder [red]{project_name}[/red] exists. Please type another name\n",
)
else:
project_name.mkdir()

View file

@ -18,7 +18,11 @@ from ...plugins.plugins_flags import list_plugins
help="Manages Manim plugins.",
)
@click.option(
"-l", "--list", "list_available", is_flag=True, help="List available plugins."
"-l",
"--list",
"list_available",
is_flag=True,
help="List available plugins.",
)
def plugins(list_available):
if list_available:

View file

@ -44,13 +44,13 @@ def render(
if args["use_opengl_renderer"]:
logger.warning(
"--use_opengl_renderer is deprecated, please use --renderer=opengl instead!"
"--use_opengl_renderer is deprecated, please use --renderer=opengl instead!",
)
args["renderer"] = "opengl"
if args["use_webgl_renderer"]:
logger.warning(
"--use_webgl_renderer is deprecated, please use --renderer=webgl instead!"
"--use_webgl_renderer is deprecated, please use --renderer=webgl instead!",
)
args["renderer"] = "webgl"
@ -68,7 +68,7 @@ def render(
if args["show_in_file_browser"]:
logger.warning(
"The short form of show_in_file_browser is deprecated and will be moved to support --format."
"The short form of show_in_file_browser is deprecated and will be moved to support --format.",
)
class ClickArgs:
@ -124,7 +124,7 @@ def render(
except ModuleNotFoundError:
console.print(
"Dependencies for the WebGL render are missing. Run "
"pip install manim[webgl_renderer] to install them."
"pip install manim[webgl_renderer] to install them.",
)
error_console.print_exception()
sys.exit(1)
@ -149,10 +149,10 @@ def render(
stable = req_info.json()["info"]["version"]
if stable != __version__:
console.print(
f"You are using manim version [red]v{__version__}[/red], but version [green]v{stable}[/green] is available."
f"You are using manim version [red]v{__version__}[/red], but version [green]v{stable}[/green] is available.",
)
console.print(
"You should consider upgrading via [yellow]pip install -U manim[/yellow]"
"You should consider upgrading via [yellow]pip install -U manim[/yellow]",
)
except requests.exceptions.HTTPError:
logger.debug(f"HTTP Error: {warn_prompt}")

View file

@ -30,7 +30,10 @@ output_options = option_group(
help="Path to store rendered videos and latex.",
),
option(
"--log_dir", type=click.Path(), help="Path to store render logs.", default=None
"--log_dir",
type=click.Path(),
help="Path to store render logs.",
default=None,
),
option(
"--log_to_file",

View file

@ -1417,7 +1417,7 @@ FetchSceneDataResponse = _reflection.GeneratedProtocolMessageType(
(_message.Message,),
{
"DESCRIPTOR": _FETCHSCENEDATARESPONSE,
"__module__": "frameserver_pb2"
"__module__": "frameserver_pb2",
# @@protoc_insertion_point(class_scope:frameserver.FetchSceneDataResponse)
},
)
@ -1428,7 +1428,7 @@ Scene = _reflection.GeneratedProtocolMessageType(
(_message.Message,),
{
"DESCRIPTOR": _SCENE,
"__module__": "frameserver_pb2"
"__module__": "frameserver_pb2",
# @@protoc_insertion_point(class_scope:frameserver.Scene)
},
)
@ -1443,7 +1443,7 @@ Animation = _reflection.GeneratedProtocolMessageType(
(_message.Message,),
{
"DESCRIPTOR": _ANIMATION_ATTRIBUTETWEENDATA,
"__module__": "frameserver_pb2"
"__module__": "frameserver_pb2",
# @@protoc_insertion_point(class_scope:frameserver.Animation.AttributeTweenData)
},
),
@ -1452,12 +1452,12 @@ Animation = _reflection.GeneratedProtocolMessageType(
(_message.Message,),
{
"DESCRIPTOR": _ANIMATION_MOBJECTTWEENDATA,
"__module__": "frameserver_pb2"
"__module__": "frameserver_pb2",
# @@protoc_insertion_point(class_scope:frameserver.Animation.MobjectTweenData)
},
),
"DESCRIPTOR": _ANIMATION,
"__module__": "frameserver_pb2"
"__module__": "frameserver_pb2",
# @@protoc_insertion_point(class_scope:frameserver.Animation)
},
)
@ -1470,7 +1470,7 @@ Updater = _reflection.GeneratedProtocolMessageType(
(_message.Message,),
{
"DESCRIPTOR": _UPDATER,
"__module__": "frameserver_pb2"
"__module__": "frameserver_pb2",
# @@protoc_insertion_point(class_scope:frameserver.Updater)
},
)
@ -1481,7 +1481,7 @@ FrameRequest = _reflection.GeneratedProtocolMessageType(
(_message.Message,),
{
"DESCRIPTOR": _FRAMEREQUEST,
"__module__": "frameserver_pb2"
"__module__": "frameserver_pb2",
# @@protoc_insertion_point(class_scope:frameserver.FrameRequest)
},
)
@ -1492,7 +1492,7 @@ Style = _reflection.GeneratedProtocolMessageType(
(_message.Message,),
{
"DESCRIPTOR": _STYLE,
"__module__": "frameserver_pb2"
"__module__": "frameserver_pb2",
# @@protoc_insertion_point(class_scope:frameserver.Style)
},
)
@ -1503,7 +1503,7 @@ Point = _reflection.GeneratedProtocolMessageType(
(_message.Message,),
{
"DESCRIPTOR": _POINT,
"__module__": "frameserver_pb2"
"__module__": "frameserver_pb2",
# @@protoc_insertion_point(class_scope:frameserver.Point)
},
)
@ -1514,7 +1514,7 @@ MobjectData = _reflection.GeneratedProtocolMessageType(
(_message.Message,),
{
"DESCRIPTOR": _MOBJECTDATA,
"__module__": "frameserver_pb2"
"__module__": "frameserver_pb2",
# @@protoc_insertion_point(class_scope:frameserver.MobjectData)
},
)
@ -1525,7 +1525,7 @@ VMobjectData = _reflection.GeneratedProtocolMessageType(
(_message.Message,),
{
"DESCRIPTOR": _VMOBJECTDATA,
"__module__": "frameserver_pb2"
"__module__": "frameserver_pb2",
# @@protoc_insertion_point(class_scope:frameserver.VMobjectData)
},
)
@ -1536,7 +1536,7 @@ ImageMobjectData = _reflection.GeneratedProtocolMessageType(
(_message.Message,),
{
"DESCRIPTOR": _IMAGEMOBJECTDATA,
"__module__": "frameserver_pb2"
"__module__": "frameserver_pb2",
# @@protoc_insertion_point(class_scope:frameserver.ImageMobjectData)
},
)
@ -1547,7 +1547,7 @@ FrameData = _reflection.GeneratedProtocolMessageType(
(_message.Message,),
{
"DESCRIPTOR": _FRAMEDATA,
"__module__": "frameserver_pb2"
"__module__": "frameserver_pb2",
# @@protoc_insertion_point(class_scope:frameserver.FrameData)
},
)
@ -1558,7 +1558,7 @@ FrameResponse = _reflection.GeneratedProtocolMessageType(
(_message.Message,),
{
"DESCRIPTOR": _FRAMERESPONSE,
"__module__": "frameserver_pb2"
"__module__": "frameserver_pb2",
# @@protoc_insertion_point(class_scope:frameserver.FrameResponse)
},
)
@ -1569,7 +1569,7 @@ EmptyRequest = _reflection.GeneratedProtocolMessageType(
(_message.Message,),
{
"DESCRIPTOR": _EMPTYREQUEST,
"__module__": "frameserver_pb2"
"__module__": "frameserver_pb2",
# @@protoc_insertion_point(class_scope:frameserver.EmptyRequest)
},
)
@ -1580,7 +1580,7 @@ EmptyResponse = _reflection.GeneratedProtocolMessageType(
(_message.Message,),
{
"DESCRIPTOR": _EMPTYRESPONSE,
"__module__": "frameserver_pb2"
"__module__": "frameserver_pb2",
# @@protoc_insertion_point(class_scope:frameserver.EmptyResponse)
},
)

View file

@ -71,7 +71,8 @@ def add_FrameServerServicer_to_server(servicer, server):
),
}
generic_handler = grpc.method_handlers_generic_handler(
"frameserver.FrameServer", rpc_method_handlers
"frameserver.FrameServer",
rpc_method_handlers,
)
server.add_generic_rpc_handlers((generic_handler,))

View file

@ -294,7 +294,7 @@ UpdateSceneDataRequest = _reflection.GeneratedProtocolMessageType(
(_message.Message,),
{
"DESCRIPTOR": _UPDATESCENEDATAREQUEST,
"__module__": "renderserver_pb2"
"__module__": "renderserver_pb2",
# @@protoc_insertion_point(class_scope:renderserver.UpdateSceneDataRequest)
},
)
@ -305,7 +305,7 @@ Scene = _reflection.GeneratedProtocolMessageType(
(_message.Message,),
{
"DESCRIPTOR": _SCENE,
"__module__": "renderserver_pb2"
"__module__": "renderserver_pb2",
# @@protoc_insertion_point(class_scope:renderserver.Scene)
},
)
@ -316,7 +316,7 @@ Animation = _reflection.GeneratedProtocolMessageType(
(_message.Message,),
{
"DESCRIPTOR": _ANIMATION,
"__module__": "renderserver_pb2"
"__module__": "renderserver_pb2",
# @@protoc_insertion_point(class_scope:renderserver.Animation)
},
)
@ -327,7 +327,7 @@ EmptyRequest = _reflection.GeneratedProtocolMessageType(
(_message.Message,),
{
"DESCRIPTOR": _EMPTYREQUEST,
"__module__": "renderserver_pb2"
"__module__": "renderserver_pb2",
# @@protoc_insertion_point(class_scope:renderserver.EmptyRequest)
},
)
@ -338,7 +338,7 @@ EmptyResponse = _reflection.GeneratedProtocolMessageType(
(_message.Message,),
{
"DESCRIPTOR": _EMPTYRESPONSE,
"__module__": "renderserver_pb2"
"__module__": "renderserver_pb2",
# @@protoc_insertion_point(class_scope:renderserver.EmptyResponse)
},
)

View file

@ -39,7 +39,8 @@ def add_RenderServerServicer_to_server(servicer, server):
),
}
generic_handler = grpc.method_handlers_generic_handler(
"renderserver.RenderServer", rpc_method_handlers
"renderserver.RenderServer",
rpc_method_handlers,
)
server.add_generic_rpc_handlers((generic_handler,))

View file

@ -81,7 +81,8 @@ class FrameServer(frameserver_pb2_grpc.FrameServerServicer):
request.first_request or self.previous_scene != requested_scene
):
previous_mobjects = extract_mobject_family_members(
self.previous_scene.mobjects, only_those_with_points=True
self.previous_scene.mobjects,
only_those_with_points=True,
)
# Remove everything from the previous scene.
ids_to_remove = [
@ -95,7 +96,8 @@ class FrameServer(frameserver_pb2_grpc.FrameServerServicer):
mobjects_to_add = [
serialize_mobject(mobject)
for mobject in extract_mobject_family_members(
requested_scene.mobjects, only_those_with_points=True
requested_scene.mobjects,
only_those_with_points=True,
)
if not isinstance(mobject, ValueTracker)
]
@ -111,7 +113,8 @@ class FrameServer(frameserver_pb2_grpc.FrameServerServicer):
flickered_mobject_ids = [
mob.original_id
for mob in extract_mobject_family_members(
animation.mobject, only_those_with_points=True
animation.mobject,
only_those_with_points=True,
)
]
else:
@ -119,14 +122,15 @@ class FrameServer(frameserver_pb2_grpc.FrameServerServicer):
# Add offset vector to submobjects.
root_mobject_center = animation.mobject.get_center()
for updated_mobject in extract_mobject_family_members(
animation.mobject, only_those_with_points=True
animation.mobject,
only_those_with_points=True,
):
mobject_tween_data_list.append(
frameserver_pb2.Animation.MobjectTweenData(
id=updated_mobject.original_id,
root_mobject_offset=updated_mobject.get_center()
- root_mobject_center,
)
),
)
animation_proto = frameserver_pb2.Animation(
name=animation.__class__.__name__,
@ -152,10 +156,11 @@ class FrameServer(frameserver_pb2_grpc.FrameServerServicer):
flickered_mobject_ids=[
mob.original_id
for mob in extract_mobject_family_members(
updated_mobject, only_those_with_points=True
updated_mobject,
only_those_with_points=True,
)
]
)
],
),
)
break
else:
@ -172,10 +177,11 @@ class FrameServer(frameserver_pb2_grpc.FrameServerServicer):
[
serialize_mobject(mobject)
for mobject in extract_mobject_family_members(
animation.mobject, only_those_with_points=True
animation.mobject,
only_those_with_points=True,
)
if not isinstance(mobject, ValueTracker)
]
],
)
for (
updated_mobject,
@ -188,15 +194,18 @@ class FrameServer(frameserver_pb2_grpc.FrameServerServicer):
[
serialize_mobject(mobject)
for mobject in extract_mobject_family_members(
updated_mobject, only_those_with_points=True
updated_mobject,
only_those_with_points=True,
)
if not isinstance(mobject, ValueTracker)
]
],
)
resp = frameserver_pb2.FrameResponse(
frame_data=frameserver_pb2.FrameData(
remove=ids_to_remove, add=mobjects_to_add, update=update_data
remove=ids_to_remove,
add=mobjects_to_add,
update=update_data,
),
scene_finished=scene_finished,
animations=animations,
@ -250,7 +259,8 @@ class FrameServer(frameserver_pb2_grpc.FrameServerServicer):
self.exception = None
try:
self.scene_class = scene_classes_from_file(
self.input_file_path, require_single_scene=True
self.input_file_path,
require_single_scene=True,
)
self.generate_keyframe_data()
except Exception as e:
@ -288,10 +298,13 @@ class FrameServer(frameserver_pb2_grpc.FrameServerServicer):
request.scene.background_color = "#000000"
else:
lines = traceback.format_exception(
None, self.exception, self.exception.__traceback__
None,
self.exception,
self.exception.__traceback__,
)
request = renderserver_pb2.UpdateSceneDataRequest(
has_exception=True, exception="\n".join(lines)
has_exception=True,
exception="\n".join(lines),
)
stub.UpdateSceneData(request)
@ -309,7 +322,7 @@ def generate_attribute_tween_data(animation):
attribute="position",
start_data=animation.starting_mobject.get_center(),
end_data=animation.target_mobject.get_center(),
)
),
)
else:
return None
@ -372,7 +385,7 @@ def serialize_mobject(mobject):
mob_proto.image_mobject_data.path = mobject.path[len(assets_dir_path) + 1 :]
else:
logger.info(
f"Expected path {mobject.path} to be under the assets dir ({assets_dir_path})"
f"Expected path {mobject.path} to be under the assets dir ({assets_dir_path})",
)
mob_proto.image_mobject_data.height = mobject.height
mob_proto.image_mobject_data.width = mobject.width
@ -386,7 +399,8 @@ def serialize_mobject(mobject):
def get(input_file_path):
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
frameserver_pb2_grpc.add_FrameServerServicer_to_server(
FrameServer(server, input_file_path), server
FrameServer(server, input_file_path),
server,
)
server.add_insecure_port("localhost:50051")
return server

View file

@ -8,7 +8,7 @@ service FrameServer {
// Returns a list of the names and durations of all animations in the scene.
rpc FetchSceneData (EmptyRequest) returns (FetchSceneDataResponse);
// Returns when the manim script changes
rpc ScriptUpdated (EmptyRequest) returns (EmptyResponse);
}

View file

@ -58,7 +58,8 @@ def configure_pygui(renderer, widgets, update=True):
dpg.add_separator()
if len(widgets) != 0:
with dpg.collapsing_header(
label=f"{config['scene_names'][0]} widgets", default_open=True
label=f"{config['scene_names'][0]} widgets",
default_open=True,
):
for widget_config in widgets:
widget_config_copy = widget_config.copy()

View file

@ -138,7 +138,9 @@ class TracedPath(VMobject, metaclass=ConvertToOpenGL):
"""
@deprecated_params(
params="min_distance_to_new_point", since="v0.10.0", until="v0.12.0"
params="min_distance_to_new_point",
since="v0.10.0",
until="v0.12.0",
)
def __init__(
self,

View file

@ -302,11 +302,7 @@ class CoordinateSystem:
The label.
"""
if (
isinstance(label_tex, float)
or isinstance(label_tex, int)
or isinstance(label_tex, str)
):
if isinstance(label_tex, (float, int, str)):
label_tex = MathTex(label_tex)
return label_tex
@ -393,7 +389,8 @@ class CoordinateSystem:
def add_coordinates(
self,
*axes_numbers: Union[
Optional[Iterable[float]], Union[Dict[float, Union[str, float, "Mobject"]]]
Optional[Iterable[float]],
Union[Dict[float, Union[str, float, "Mobject"]]],
],
**kwargs,
):
@ -992,7 +989,7 @@ class CoordinateSystem:
self.coords_to_point(x + width_scale_factor * dx, y_point),
graph_point,
],
)
),
)
)
@ -1085,7 +1082,10 @@ class CoordinateSystem:
).set_opacity(opacity=opacity)
def angle_of_tangent(
self, x: float, graph: "ParametricFunction", dx: float = 1e-8
self,
x: float,
graph: "ParametricFunction",
dx: float = 1e-8,
) -> float:
"""Returns the angle to the x-axis of the tangent
to the plotted curve at a particular x-value.
@ -1311,20 +1311,24 @@ class CoordinateSystem:
if dx_label is not None:
group.dx_label.next_to(
group.dx_line, np.sign(dx) * DOWN, buff=group.dx_label.height / 2
group.dx_line,
np.sign(dx) * DOWN,
buff=group.dx_label.height / 2,
)
group.dx_label.set_color(group.dx_line.get_color())
if dy_label is not None:
group.df_label.next_to(
group.df_line, np.sign(dx) * RIGHT, buff=group.df_label.height / 2
group.df_line,
np.sign(dx) * RIGHT,
buff=group.df_label.height / 2,
)
group.df_label.set_color(group.df_line.get_color())
if include_secant_line:
group.secant_line = Line(p1, p2, color=secant_line_color)
group.secant_line.scale_in_place(
secant_line_length / group.secant_line.get_length()
secant_line_length / group.secant_line.get_length(),
)
group.add(group.secant_line)
return group
@ -1443,7 +1447,8 @@ class CoordinateSystem:
T_label_group = VGroup()
triangle = RegularPolygon(n=3, start_angle=np.pi / 2, stroke_width=0).set_fill(
color=triangle_color, opacity=1
color=triangle_color,
opacity=1,
)
triangle.height = triangle_size
triangle.move_to(self.coords_to_point(x_val, 0), UP)
@ -1453,7 +1458,9 @@ class CoordinateSystem:
T_label_group.add(t_label)
v_line = self.get_vertical_line(
self.i2gp(x_val, graph), color=line_color, line_func=line_func
self.i2gp(x_val, graph),
color=line_color,
line_func=line_func,
)
T_label_group.add(triangle, v_line)
@ -1515,10 +1522,12 @@ class Axes(VGroup, CoordinateSystem, metaclass=ConvertToOpenGL):
)
self.x_axis_config = merge_dicts_recursively(
self.axis_config, self.x_axis_config
self.axis_config,
self.x_axis_config,
)
self.y_axis_config = merge_dicts_recursively(
self.axis_config, self.y_axis_config
self.axis_config,
self.y_axis_config,
)
self.x_axis = self._create_axis(self.x_range, self.x_axis_config, self.x_length)
@ -1832,7 +1841,8 @@ class ThreeDAxes(Axes):
self.z_axis_config = {}
self._update_default_configs((self.z_axis_config,), (z_axis_config,))
self.z_axis_config = merge_dicts_recursively(
self.axis_config, self.z_axis_config
self.axis_config,
self.z_axis_config,
)
self.z_normal = z_normal
@ -1852,7 +1862,7 @@ class ThreeDAxes(Axes):
self.add(z_axis)
self.z_axis = z_axis
if not config.renderer == "opengl":
if config.renderer != "opengl":
self._add_3d_pieces()
self._set_axis_shading()
@ -2299,7 +2309,7 @@ class PolarPlane(Axes):
self.azimuth_units = azimuth_units
else:
raise ValueError(
"Invalid azimuth units. Expected one of: PI radians, TAU radians, degrees, gradians or None."
"Invalid azimuth units. Expected one of: PI radians, TAU radians, degrees, gradians or None.",
)
if azimuth_direction in ["CW", "CCW"]:
@ -2552,7 +2562,7 @@ class PolarPlane(Axes):
self.get_right()[0]
* np.sin(d * (i * TAU) + self.azimuth_offset),
0,
]
],
),
}
for i in a_values
@ -2560,7 +2570,8 @@ class PolarPlane(Axes):
if self.azimuth_units == "PI radians" or self.azimuth_units == "TAU radians":
a_tex = [
self.get_radian_label(
i["label"], font_size=self.azimuth_label_font_size
i["label"],
font_size=self.azimuth_label_font_size,
).next_to(
i["point"],
direction=i["point"],
@ -2598,7 +2609,8 @@ class PolarPlane(Axes):
elif self.azimuth_units is None:
a_tex = [
MathTex(
f'{i["label"]:g}', font_size=self.azimuth_label_font_size
f'{i["label"]:g}',
font_size=self.azimuth_label_font_size,
).next_to(
i["point"],
direction=i["point"],

View file

@ -77,7 +77,8 @@ class ParametricFunction(VMobject, metaclass=ConvertToOpenGL):
def generate_points(self):
discontinuities = filter(
lambda t: self.t_min <= t <= self.t_max, self.discontinuities
lambda t: self.t_min <= t <= self.t_max,
self.discontinuities,
)
discontinuities = np.array(list(discontinuities))
boundary_times = np.array(
@ -86,7 +87,7 @@ class ParametricFunction(VMobject, metaclass=ConvertToOpenGL):
self.t_max,
*(discontinuities - self.dt),
*(discontinuities + self.dt),
]
],
)
boundary_times.sort()
for t1, t2 in zip(boundary_times[0::2], boundary_times[1::2]):

View file

@ -179,7 +179,7 @@ class TipableVMobject(VMobject, metaclass=ConvertToOpenGL):
anchor = self.get_end()
angles = cartesian_to_spherical(handle - anchor)
tip.rotate(
angles[2] - PI - tip.tip_angle
angles[2] - PI - tip.tip_angle,
) # Rotates the tip along the azimuthal
axis = [
np.sin(angles[2]),
@ -187,7 +187,8 @@ class TipableVMobject(VMobject, metaclass=ConvertToOpenGL):
0,
] # Obtains the perpendicular of the tip
tip.rotate(
-angles[1] + PI / 2, axis=axis
-angles[1] + PI / 2,
axis=axis,
) # Rotates the tip along the vertical wrt the axis
tip.shift(anchor - tip.tip_point)
return tip
@ -327,7 +328,7 @@ class Arc(TipableVMobject):
angle=self.angle,
start_angle=self.start_angle,
n_components=self.num_components,
)
),
)
self.scale(self.radius, about_point=ORIGIN)
self.shift(self.arc_center)
@ -342,7 +343,7 @@ class Arc(TipableVMobject):
start_angle + angle,
2 * n_components + 1,
)
]
],
)
theta = angle / n_components
samples[1::2] /= np.cos(theta / 2)
@ -358,9 +359,11 @@ class Arc(TipableVMobject):
[
np.cos(a) * RIGHT + np.sin(a) * UP
for a in np.linspace(
self.start_angle, self.start_angle + self.angle, self.num_components
self.start_angle,
self.start_angle + self.angle,
self.num_components,
)
]
],
)
# Figure out which control points will give the
# Appropriate tangent lines to the circle
@ -441,7 +444,7 @@ class ArcBetweenPoints(Arc):
if radius < halfdist:
raise ValueError(
"""ArcBetweenPoints called with a radius that is
smaller than half the distance between the points."""
smaller than half the distance between the points.""",
)
arc_height = radius - math.sqrt(radius ** 2 - halfdist ** 2)
angle = math.acos((radius - arc_height) / radius) * sign
@ -957,7 +960,10 @@ class Line(TipableVMobject):
def generate_points(self):
self.set_points_by_ends(
start=self.start, end=self.end, buff=self.buff, path_arc=self.path_arc
start=self.start,
end=self.end,
buff=self.buff,
path_arc=self.path_arc,
)
def set_points_by_ends(self, start, end, buff=0, path_arc=0):
@ -1140,7 +1146,8 @@ class DashedLine(Line):
**kwargs,
):
self.dash_spacing = kwargs.pop(
"dash_spacing", None
"dash_spacing",
None,
) # Unused param, remove with deprecation warning
self.dash_length = dash_length
self.dashed_ratio = dashed_ratio
@ -1166,7 +1173,8 @@ class DashedLine(Line):
# Minimum number of dashes has to be 2
return max(
2, int(np.ceil((self.get_length() / self.dash_length) * self.dashed_ratio))
2,
int(np.ceil((self.get_length() / self.dash_length) * self.dashed_ratio)),
)
def get_start(self) -> np.ndarray:
@ -1557,7 +1565,10 @@ class Vector(Arrow):
super().__init__(ORIGIN, direction, buff=buff, **kwargs)
def coordinate_label(
self, integer_labels: bool = True, n_dim: int = 2, color: str = WHITE
self,
integer_labels: bool = True,
n_dim: int = 2,
color: str = WHITE,
):
"""Creates a label based on the coordinates of the vector.
@ -1737,7 +1748,7 @@ class Polygram(VMobject, metaclass=ConvertToOpenGL):
self.start_new_path(first_vertex)
self.add_points_as_corners(
[*(np.array(vertex) for vertex in vertices), first_vertex]
[*(np.array(vertex) for vertex in vertices), first_vertex],
)
def get_vertices(self) -> np.ndarray:
@ -1973,7 +1984,9 @@ class RegularPolygram(Polygram):
# polygon vertices.
def gen_polygon_vertices(start_angle):
reg_vertices, start_angle = regular_vertices(
num_vertices, radius=radius, start_angle=start_angle
num_vertices,
radius=radius,
start_angle=start_angle,
)
vertices = []
@ -2108,7 +2121,7 @@ class Star(Polygon):
if density <= 0 or density >= n / 2:
raise ValueError(
f"Incompatible density {density} for number of points {n}"
f"Incompatible density {density} for number of points {n}",
)
outer_angle = TAU * density / n
@ -2119,10 +2132,14 @@ class Star(Polygon):
inner_radius = outer_radius / (np.cos(inner_angle) * inverse_x)
outer_vertices, self.start_angle = regular_vertices(
n, radius=outer_radius, start_angle=start_angle
n,
radius=outer_radius,
start_angle=start_angle,
)
inner_vertices, _ = regular_vertices(
n, radius=inner_radius, start_angle=self.start_angle + inner_angle
n,
radius=inner_radius,
start_angle=self.start_angle + inner_angle,
)
vertices = []
@ -2350,7 +2367,7 @@ class ArcPolygonFromArcs(VMobject, metaclass=ConvertToOpenGL):
def __init__(self, *arcs, **kwargs):
if not all(isinstance(m, (Arc, ArcBetweenPoints)) for m in arcs):
raise ValueError(
"All ArcPolygon submobjects must be of type Arc/ArcBetweenPoints"
"All ArcPolygon submobjects must be of type Arc/ArcBetweenPoints",
)
super().__init__(**kwargs)
# Adding the arcs like this makes ArcPolygonFromArcs double as a VGroup.
@ -2952,7 +2969,8 @@ class Angle(VMobject, metaclass=ConvertToOpenGL):
self.dot_distance = dot_distance
self.elbow = elbow
inter = line_intersection(
[line1.get_start(), line1.get_end()], [line2.get_start(), line2.get_end()]
[line1.get_start(), line1.get_end()],
[line2.get_start(), line2.get_end()],
)
if radius is None:
@ -2982,7 +3000,7 @@ class Angle(VMobject, metaclass=ConvertToOpenGL):
)
angle_mobject = Elbow(**kwargs)
angle_mobject.set_points_as_corners(
[anchor_angle_1, anchor_middle, anchor_angle_2]
[anchor_angle_1, anchor_middle, anchor_angle_2],
)
else:
angle_1 = angle_of_vector(anchor_angle_1 - inter)

View file

@ -64,14 +64,14 @@ def _determine_graph_layout(
elif layout == "partite":
if partitions is None or len(partitions) == 0:
raise ValueError(
"The partite layout requires the 'partitions' parameter to contain the partition of the vertices"
"The partite layout requires the 'partitions' parameter to contain the partition of the vertices",
)
partition_count = len(partitions)
for i in range(partition_count):
for v in partitions[i]:
if nx_graph.nodes[v] is None:
raise ValueError(
"The partition must contain arrays of vertices in the graph"
"The partition must contain arrays of vertices in the graph",
)
nx_graph.nodes[v]["subset"] = i
# Add missing vertices to their own side
@ -93,7 +93,7 @@ def _determine_graph_layout(
else:
raise ValueError(
f"The layout '{layout}' is neither a recognized automatic layout, "
"nor a vertex placement dictionary."
"nor a vertex placement dictionary.",
)
@ -132,7 +132,7 @@ def _tree_layout(
else:
for i in range(new_row_length):
result[new_row[i]] = np.array(
[-1 + 2 * i / (new_row_length - 1), current_height, 0]
[-1 + 2 * i / (new_row_length - 1), current_height, 0],
)
_recursive_position_for_row(
@ -144,7 +144,11 @@ def _tree_layout(
)
_recursive_position_for_row(
G, result, two_rows_before=[], last_row=[root_vertex], current_height=1
G,
result,
two_rows_before=[],
last_row=[root_vertex],
current_height=1,
)
height = max(map(lambda v: result[v][1], result))
@ -507,7 +511,7 @@ class Graph(VMobject, metaclass=ConvertToOpenGL):
if vertex in self.vertices:
raise ValueError(
f"Vertex identifier '{vertex}' is already used for a vertex in this graph."
f"Vertex identifier '{vertex}' is already used for a vertex in this graph.",
)
self._graph.add_node(vertex)
@ -601,7 +605,7 @@ class Graph(VMobject, metaclass=ConvertToOpenGL):
assert isinstance(vertex_config, dict)
base_vertex_config = copy(self.default_vertex_config)
base_vertex_config.update(
{key: val for key, val in vertex_config.items() if key not in vertices}
{key: val for key, val in vertex_config.items() if key not in vertices},
)
vertex_config = {
v: (vertex_config[v] if v in vertex_config else copy(base_vertex_config))
@ -649,7 +653,7 @@ class Graph(VMobject, metaclass=ConvertToOpenGL):
"""
if vertex not in self.vertices:
raise ValueError(
f"The graph does not contain a vertex with identifier '{vertex}'"
f"The graph does not contain a vertex with identifier '{vertex}'",
)
self._graph.remove_node(vertex)
@ -796,7 +800,9 @@ class Graph(VMobject, metaclass=ConvertToOpenGL):
added_mobjects = sum(
(
self._add_edge(
edge, edge_type=edge_type, edge_config=edge_config[edge]
edge,
edge_type=edge_type,
edge_config=edge_config[edge],
).submobjects
for edge in edges
),

View file

@ -145,7 +145,10 @@ class ManimBanner(VGroup):
return AnimationGroup(
UpdateFromAlphaFunc(
self.shapes, spiral_updater, run_time=run_time, rate_func=ease_out_sine
self.shapes,
spiral_updater,
run_time=run_time,
rate_func=ease_out_sine,
),
FadeIn(self.M, run_time=run_time / 2),
lag_ratio=0.1,
@ -257,6 +260,9 @@ class ManimBanner(VGroup):
rate_func=ease_in_out_cubic,
),
UpdateFromAlphaFunc(
self, slide_back, run_time=run_time * 1 / 3, rate_func=smooth
self,
slide_back,
run_time=run_time * 1 / 3,
rate_func=smooth,
),
)

View file

@ -532,7 +532,10 @@ class MobjectMatrix(Matrix):
def get_det_text(
matrix, determinant=None, background_rect=False, initial_scale_factor=2
matrix,
determinant=None,
background_rect=False,
initial_scale_factor=2,
):
r"""Helper function to create determinant.

View file

@ -41,6 +41,7 @@ from ..utils.color import (
color_gradient,
interpolate_color,
)
from ..utils.deprecation import deprecated
from ..utils.exceptions import MultiAnimationOverrideException
from ..utils.iterables import list_update, remove_list_redundancies
from ..utils.paths import straight_path
@ -89,7 +90,8 @@ class Mobject:
super().__init_subclass__(**kwargs)
cls.animation_overrides: Dict[
Type["Animation"], Callable[["Mobject"], "Animation"]
Type["Animation"],
Callable[["Mobject"], "Animation"],
] = {}
cls._add_intrinsic_animation_overrides()
@ -109,7 +111,8 @@ class Mobject:
@classmethod
def animation_override_for(
cls, animation_class: Type["Animation"]
cls,
animation_class: Type["Animation"],
) -> "Optional[Callable[[Mobject, ...], Animation]]":
"""Returns the function defining a specific animation override for this class.
@ -174,7 +177,7 @@ class Mobject:
f"The animation {animation_class.__name__} for "
f"{cls.__name__} is overridden by more than one method: "
f"{cls.animation_overrides[animation_class].__qualname__} and "
f"{override_func.__qualname__}."
f"{override_func.__qualname__}.",
)
@property
@ -684,7 +687,7 @@ class Mobject:
"""Saves an image of only this :class:`Mobject` at its position to a png
file."""
self.get_image().save(
Path(config.get_dir("video_dir")).joinpath((name or str(self)) + ".png")
Path(config.get_dir("video_dir")).joinpath((name or str(self)) + ".png"),
)
def copy(self: T) -> T:
@ -781,10 +784,7 @@ class Mobject:
:meth:`get_time_based_updaters`
"""
for updater in self.updaters:
if "dt" in get_parameters(updater):
return True
return False
return any("dt" in get_parameters(updater) for updater in self.updaters)
def get_updaters(self) -> List[Updater]:
"""Return all updaters.
@ -1253,7 +1253,10 @@ class Mobject:
# above methods
def apply_points_function_about_point(
self, func, about_point=None, about_edge=None
self,
func,
about_point=None,
about_edge=None,
):
if about_point is None:
if about_edge is None:
@ -1536,7 +1539,10 @@ class Mobject:
return self
def move_to(
self, point_or_mobject, aligned_edge=ORIGIN, coor_mask=np.array([1, 1, 1])
self,
point_or_mobject,
aligned_edge=ORIGIN,
coor_mask=np.array([1, 1, 1]),
):
"""Move center of the :class:`~.Mobject` to certain coordinate."""
if isinstance(point_or_mobject, Mobject):
@ -1555,13 +1561,19 @@ class Mobject:
self.stretch_to_fit_height(mobject.height)
else:
self.rescale_to_fit(
mobject.length_over_dim(dim_to_match), dim_to_match, stretch=False
mobject.length_over_dim(dim_to_match),
dim_to_match,
stretch=False,
)
self.shift(mobject.get_center() - self.get_center())
return self
def surround(
self, mobject: "Mobject", dim_to_match=0, stretch=False, buff=MED_SMALL_BUFF
self,
mobject: "Mobject",
dim_to_match=0,
stretch=False,
buff=MED_SMALL_BUFF,
):
self.replace(mobject, dim_to_match, stretch)
length = mobject.length_over_dim(dim_to_match)
@ -1662,10 +1674,17 @@ class Mobject:
return self
def set_colors_by_radial_gradient(
self, center=None, radius=1, inner_color=WHITE, outer_color=BLACK
self,
center=None,
radius=1,
inner_color=WHITE,
outer_color=BLACK,
):
self.set_submobject_colors_by_radial_gradient(
center, radius, inner_color, outer_color
center,
radius,
inner_color,
outer_color,
)
return self
@ -1683,7 +1702,11 @@ class Mobject:
return self
def set_submobject_colors_by_radial_gradient(
self, center=None, radius=1, inner_color=WHITE, outer_color=BLACK
self,
center=None,
radius=1,
inner_color=WHITE,
outer_color=BLACK,
):
if center is None:
center = self.get_center()
@ -1805,7 +1828,9 @@ class Mobject:
return result
for dim in range(self.dim):
result[dim] = self.get_extremum_along_dim(
all_points, dim=dim, key=direction[dim]
all_points,
dim=dim,
key=direction[dim],
)
return result
@ -1880,9 +1905,14 @@ class Mobject:
def length_over_dim(self, dim):
"""Measure the length of an :class:`~.Mobject` in a certain direction."""
return self.reduce_across_dimension(
np.max, np.max, dim
) - self.reduce_across_dimension(np.min, np.min, dim)
return (
self.reduce_across_dimension(
np.max,
np.max,
dim,
)
- self.reduce_across_dimension(np.min, np.min, dim)
)
def get_coord(self, dim, direction=ORIGIN):
"""Meant to generalize ``get_x``, ``get_y`` and ``get_z``"""
@ -2223,10 +2253,18 @@ class Mobject:
return alignments
row_alignments = init_alignments(
row_alignments, rows, {"u": UP, "c": ORIGIN, "d": DOWN}, "row", RIGHT
row_alignments,
rows,
{"u": UP, "c": ORIGIN, "d": DOWN},
"row",
RIGHT,
)
col_alignments = init_alignments(
col_alignments, cols, {"l": LEFT, "c": ORIGIN, "r": RIGHT}, "col", UP
col_alignments,
cols,
{"l": LEFT, "c": ORIGIN, "r": RIGHT},
"col",
UP,
)
# Now row_alignment[r] + col_alignment[c] is the alignment in cell [r][c]
@ -2242,7 +2280,7 @@ class Mobject:
}
if flow_order not in mapper:
raise ValueError(
'flow_order must be one of the following values: "dr", "rd", "ld" "dl", "ru", "ur", "lu", "ul".'
'flow_order must be one of the following values: "dr", "rd", "ld" "dl", "ru", "ur", "lu", "ul".',
)
flow_order = mapper[flow_order]
@ -2552,7 +2590,7 @@ class Mobject:
if self.has_no_points():
caller_name = sys._getframe(1).f_code.co_name
raise Exception(
f"Cannot call Mobject.{caller_name} for a Mobject with no points"
f"Cannot call Mobject.{caller_name} for a Mobject with no points",
)
# About z-index
@ -2636,7 +2674,7 @@ class _AnimationBuilder:
def __call__(self, **kwargs):
if self.cannot_pass_args:
raise ValueError(
"Animation arguments must be passed before accessing methods and can only be passed once"
"Animation arguments must be passed before accessing methods and can only be passed once",
)
self.anim_args = kwargs
@ -2652,7 +2690,7 @@ class _AnimationBuilder:
if (self.is_chaining and has_overridden_animation) or self.overridden_animation:
raise NotImplementedError(
"Method chaining is currently not supported for "
"overridden animations"
"overridden animations",
)
def update_target(*method_args, **method_kwargs):

View file

@ -331,7 +331,8 @@ class NumberLine(Line):
**number_config,
) -> DecimalNumber:
number_config = merge_dicts_recursively(
self.decimal_number_config, number_config
self.decimal_number_config,
number_config,
)
if direction is None:
direction = self.label_direction
@ -422,7 +423,7 @@ class NumberLine(Line):
The label.
"""
if isinstance(label_tex, float) or isinstance(label_tex, int):
if isinstance(label_tex, (float, int)):
label_tex = MathTex(label_tex)
elif isinstance(label_tex, str):
label_tex = Tex(label_tex)

View file

@ -90,7 +90,7 @@ class DecimalNumber(VMobject, metaclass=ConvertToOpenGL):
"font_size": font_size,
"stroke_width": stroke_width,
"fill_opacity": fill_opacity,
}
},
)
self.set_submobjects_from_number(number)
@ -123,7 +123,7 @@ class DecimalNumber(VMobject, metaclass=ConvertToOpenGL):
# Add non-numerical bits
if self.show_ellipsis:
self.add(
self.string_to_mob("\\dots", SingleStringMathTex, color=self.color)
self.string_to_mob("\\dots", SingleStringMathTex, color=self.color),
)
if self.unit is not None:
@ -131,7 +131,8 @@ class DecimalNumber(VMobject, metaclass=ConvertToOpenGL):
self.add(self.unit_sign)
self.arrange(
buff=self.digit_buff_per_font_unit * self._font_size, aligned_edge=DOWN
buff=self.digit_buff_per_font_unit * self._font_size,
aligned_edge=DOWN,
)
# Handle alignment of parts that should be aligned
@ -204,7 +205,7 @@ class DecimalNumber(VMobject, metaclass=ConvertToOpenGL):
str(config["num_decimal_places"]),
"f",
"}",
]
],
)
def get_complex_formatter(self):
@ -213,7 +214,7 @@ class DecimalNumber(VMobject, metaclass=ConvertToOpenGL):
self.get_formatter(field_name="0.real"),
self.get_formatter(field_name="0.imag", include_sign=True),
"i",
]
],
)
def set_value(self, number: float):
@ -400,13 +401,15 @@ class Variable(VMobject, metaclass=ConvertToOpenGL):
if var_type == DecimalNumber:
self.value = DecimalNumber(
self.tracker.get_value(), num_decimal_places=num_decimal_places
self.tracker.get_value(),
num_decimal_places=num_decimal_places,
)
elif var_type == Integer:
self.value = Integer(self.tracker.get_value())
self.value.add_updater(lambda v: v.set_value(self.tracker.get_value())).next_to(
self.label, RIGHT
self.label,
RIGHT,
)
super().__init__(**kwargs)

View file

@ -219,7 +219,7 @@ class OpenGLArc(OpenGLTipableVMobject):
angle=self.angle,
start_angle=self.start_angle,
n_components=self.n_components,
)
),
)
# To maintain proper orientation for fill shaders.
self.scale(self.radius, about_point=ORIGIN)
@ -235,7 +235,7 @@ class OpenGLArc(OpenGLTipableVMobject):
start_angle + angle,
2 * n_components + 1,
)
]
],
)
theta = angle / n_components
samples[1::2] /= np.cos(theta / 2)
@ -541,14 +541,17 @@ class OpenGLDashedLine(OpenGLLine):
dashed_ratio = self.dashed_ratio
num_dashes = self.calculate_num_dashes(dashed_ratio)
dashes = OpenGLDashedVMobject(
self, num_dashes=num_dashes, dashed_ratio=dashed_ratio
self,
num_dashes=num_dashes,
dashed_ratio=dashed_ratio,
)
self.clear_points()
self.add(*dashes)
def calculate_num_dashes(self, dashed_ratio):
return max(
2, int(np.ceil((self.get_length() / self.dash_length) * dashed_ratio))
2,
int(np.ceil((self.get_length() / self.dash_length) * dashed_ratio)),
)
def get_start(self):
@ -688,7 +691,9 @@ class OpenGLArrow(OpenGLLine):
def reset_points_around_ends(self):
self.set_points_by_ends(
self.get_start(), self.get_end(), path_arc=self.path_arc
self.get_start(),
self.get_end(),
path_arc=self.path_arc,
)
return self

View file

@ -285,7 +285,11 @@ class OpenGLMobject:
return self.point_from_proportion(0.5)
def apply_points_function(
self, func, about_point=None, about_edge=ORIGIN, works_on_bounding_box=False
self,
func,
about_point=None,
about_edge=ORIGIN,
works_on_bounding_box=False,
):
if about_point is None and about_edge is not None:
about_point = self.get_bounding_box_point(about_edge)
@ -349,7 +353,7 @@ class OpenGLMobject:
for mob in self.get_family()[1:]
if mob.has_points()
),
]
],
)
if len(all_points) == 0:
return np.zeros((3, self.dim))
@ -654,10 +658,18 @@ class OpenGLMobject:
return alignments
row_alignments = init_alignments(
row_alignments, rows, {"u": UP, "c": ORIGIN, "d": DOWN}, "row", RIGHT
row_alignments,
rows,
{"u": UP, "c": ORIGIN, "d": DOWN},
"row",
RIGHT,
)
col_alignments = init_alignments(
col_alignments, cols, {"l": LEFT, "c": ORIGIN, "r": RIGHT}, "col", UP
col_alignments,
cols,
{"l": LEFT, "c": ORIGIN, "r": RIGHT},
"col",
UP,
)
# Now row_alignment[r] + col_alignment[c] is the alignment in cell [r][c]
@ -673,7 +685,7 @@ class OpenGLMobject:
}
if flow_order not in mapper:
raise ValueError(
'flow_order must be one of the following values: "dr", "rd", "ld" "dl", "ru", "ur", "lu", "ul".'
'flow_order must be one of the following values: "dr", "rd", "ld" "dl", "ru", "ur", "lu", "ul".',
)
flow_order = mapper[flow_order]
@ -1047,7 +1059,7 @@ class OpenGLMobject:
+ np.dot(
alphas.reshape((len(alphas), 1)),
np.array(direction).reshape((1, mob.dim)),
)
),
)
return self
@ -1096,7 +1108,7 @@ class OpenGLMobject:
else:
target_aligner = mob
target_point = target_aligner.get_bounding_box_point(
aligned_edge + direction
aligned_edge + direction,
)
else:
target_point = mobject_or_point
@ -1194,7 +1206,10 @@ class OpenGLMobject:
return self
def move_to(
self, point_or_mobject, aligned_edge=ORIGIN, coor_mask=np.array([1, 1, 1])
self,
point_or_mobject,
aligned_edge=ORIGIN,
coor_mask=np.array([1, 1, 1]),
):
if isinstance(point_or_mobject, OpenGLMobject):
target = point_or_mobject.get_bounding_box_point(aligned_edge)
@ -1213,7 +1228,9 @@ class OpenGLMobject:
self.rescale_to_fit(mobject.length_over_dim(i), i, stretch=True)
else:
self.rescale_to_fit(
mobject.length_over_dim(dim_to_match), dim_to_match, stretch=False
mobject.length_over_dim(dim_to_match),
dim_to_match,
stretch=False,
)
self.shift(mobject.get_center() - self.get_center())
return self
@ -1410,8 +1427,8 @@ class OpenGLMobject:
corner_vect,
out=np.zeros(len(direction)),
where=((corner_vect) != 0),
)
)
),
),
)
def get_top(self):
@ -1647,7 +1664,9 @@ class OpenGLMobject:
self.data[key][:] = func(mobject1.data[key], mobject2.data[key], alpha)
for key in self.uniforms:
self.uniforms[key] = interpolate(
mobject1.uniforms[key], mobject2.uniforms[key], alpha
mobject1.uniforms[key],
mobject2.uniforms[key],
alpha,
)
return self
@ -1690,7 +1709,9 @@ class OpenGLMobject:
def lock_matching_data(self, mobject1, mobject2):
for sm, sm1, sm2 in zip(
self.get_family(), mobject1.get_family(), mobject2.get_family()
self.get_family(),
mobject1.get_family(),
mobject2.get_family(),
):
keys = sm.data.keys() & sm1.data.keys() & sm2.data.keys()
sm.lock_data(
@ -1698,8 +1719,8 @@ class OpenGLMobject:
filter(
lambda key: np.all(sm1.data[key] == sm2.data[key]),
keys,
)
)
),
),
)
return self
@ -1760,7 +1781,11 @@ class OpenGLMobject:
return self
def set_color_by_xyz_func(
self, glsl_snippet, min_value=-5.0, max_value=5.0, colormap="viridis"
self,
glsl_snippet,
min_value=-5.0,
max_value=5.0,
colormap="viridis",
):
"""
Pass in a glsl expression in terms of x, y and z which returns
@ -1777,7 +1802,7 @@ class OpenGLMobject:
float(min_value),
float(max_value),
get_colormap_code(rgb_list),
)
),
)
return self
@ -1825,7 +1850,8 @@ class OpenGLMobject:
d_len = len(self.data[data_key])
if d_len != 1 and d_len != len(array):
self.data[data_key] = resize_with_interpolation(
self.data[data_key], len(array)
self.data[data_key],
len(array),
)
return self
@ -1999,7 +2025,7 @@ class _AnimationBuilder:
def __call__(self, **kwargs):
if self.cannot_pass_args:
raise ValueError(
"Animation arguments must be passed before accessing methods and can only be passed once"
"Animation arguments must be passed before accessing methods and can only be passed once",
)
self.anim_args = kwargs
@ -2015,7 +2041,7 @@ class _AnimationBuilder:
if (self.is_chaining and has_overridden_animation) or self.overridden_animation:
raise NotImplementedError(
"Method chaining is currently not supported for "
"overridden animations"
"overridden animations",
)
def update_target(*method_args, **method_kwargs):

View file

@ -124,7 +124,8 @@ class Polyhedron(VGroup):
return edges
def create_faces(
self, face_coords: List[List[Union[List, np.ndarray]]]
self,
face_coords: List[List[Union[List, np.ndarray]]],
) -> "VGroup":
"""Creates VGroup of faces from a list of face coordinates."""
face_group = VGroup()

View file

@ -119,7 +119,12 @@ class SampleSpace(Rectangle):
self.add(self.vertical_parts)
def get_subdivision_braces_and_labels(
self, parts, labels, direction, buff=SMALL_BUFF, min_num_quads=1
self,
parts,
labels,
direction,
buff=SMALL_BUFF,
min_num_quads=1,
):
label_mobs = VGroup()
braces = VGroup()

View file

@ -93,11 +93,13 @@ class Brace(SVGPathMobject):
right = mobject.get_corner(DOWN + RIGHT)
target_width = right[0] - left[0]
linear_section_length = max(
0, (target_width * sharpness - default_min_width) / 2
0,
(target_width * sharpness - default_min_width) / 2,
)
path = path_string_template.format(
linear_section_length, -linear_section_length
linear_section_length,
-linear_section_length,
)
SVGPathMobject.__init__(
@ -179,7 +181,7 @@ class BraceLabel(VMobject, metaclass=ConvertToOpenGL):
obj = self.get_group_class()(*obj)
self.brace = Brace(obj, brace_direction, buff, **kwargs)
if isinstance(text, tuple) or isinstance(text, list):
if isinstance(text, (tuple, list)):
self.label = self.label_constructor(font_size=font_size, *text, **kwargs)
else:
self.label = self.label_constructor(str(text), font_size=font_size)

View file

@ -215,7 +215,7 @@ class Code(VGroup):
self.code_string = code
else:
raise ValueError(
"Neither a code file nor a code string have been specified."
"Neither a code file nor a code string have been specified.",
)
if isinstance(self.style, str):
self.style = self.style.lower()
@ -269,7 +269,7 @@ class Code(VGroup):
buttons = VGroup(red_button, yellow_button, green_button)
buttons.shift(
UP * (height / 2 - 0.1 * 2 - 0.05)
+ LEFT * (width / 2 - 0.1 * 5 - self.corner_radius / 2 - 0.05)
+ LEFT * (width / 2 - 0.1 * 5 - self.corner_radius / 2 - 0.05),
)
self.background_mobject = VGroup(rect, buttons)
@ -380,16 +380,19 @@ class Code(VGroup):
if self.generate_html_file:
os.makedirs(
os.path.join("assets", "codes", "generated_html_files"), exist_ok=True
os.path.join("assets", "codes", "generated_html_files"),
exist_ok=True,
)
file = open(
with open(
os.path.join(
"assets", "codes", "generated_html_files", self.file_name + ".html"
"assets",
"codes",
"generated_html_files",
self.file_name + ".html",
),
"w",
)
file.write(self.html_string)
file.close()
) as file:
file.write(self.html_string)
def gen_code_json(self):
"""Function to background_color, generate code_json and tab_spaces from html_string.
@ -413,7 +416,8 @@ class Code(VGroup):
self.html_string = self.html_string.replace("</" + " " * i, "</")
for i in range(10, -1, -1):
self.html_string = self.html_string.replace(
"</span>" + " " * i, " " * i + "</span>"
"</span>" + " " * i,
" " * i + "</span>",
)
self.html_string = self.html_string.replace("background-color:", "background:")
@ -440,7 +444,7 @@ class Code(VGroup):
start_point = lines[line_index].find("<")
starting_string = lines[line_index][:start_point]
indentation_chars_count = lines[line_index][:start_point].count(
self.indentation_chars
self.indentation_chars,
)
if (
starting_string.__len__()
@ -538,7 +542,13 @@ class Code(VGroup):
def hilite_me(
code, language, style, insert_line_no, divstyles, file_path, line_no_from
code,
language,
style,
insert_line_no,
divstyles,
file_path,
line_no_from,
):
"""Function to highlight code from string to html.
@ -575,7 +585,7 @@ def hilite_me(
html = highlight(code, lexer, formatter)
elif language is None:
raise ValueError(
"The code language has to be specified when rendering a code string"
"The code language has to be specified when rendering a code string",
)
else:
html = highlight(code, get_lexer_by_name(language, **{}), formatter)
@ -612,6 +622,7 @@ def insert_line_numbers_in_html(html, line_no_from):
format_lines = "%" + str(len(str(numbers[-1]))) + "i"
lines = "\n".join(format_lines % i for i in numbers)
html = html.replace(
pre_open, "<table><tr><td>" + pre_open + lines + "</pre></td><td>" + pre_open
pre_open,
"<table><tr><td>" + pre_open + lines + "</pre></td><td>" + pre_open,
)
return html

View file

@ -414,7 +414,8 @@ class OpenGLMathTex(OpenGLSingleStringMathTex):
def break_up_tex_strings(self, tex_strings):
substrings_to_isolate = op.add(
self.substrings_to_isolate, list(self.tex_to_color_map.keys())
self.substrings_to_isolate,
list(self.tex_to_color_map.keys()),
)
split_list = split_string_list_to_isolate_substrings(
tex_strings, *substrings_to_isolate

View file

@ -148,7 +148,7 @@ class OpenGLParagraph(OpenGLVGroup):
char_index_counter : char_index_counter
+ lines_str_list[line_index].__len__()
+ 1
]
],
)
char_index_counter += lines_str_list[line_index].__len__() + 1
self.lines = []
@ -160,7 +160,7 @@ class OpenGLParagraph(OpenGLVGroup):
self.lines_initial_positions.append(self.lines[0][line_no].get_center())
self.lines.append([])
self.lines[1].extend(
[self.alignment for _ in range(chars_lines_text_list.__len__())]
[self.alignment for _ in range(chars_lines_text_list.__len__())],
)
OpenGLVGroup.__init__(
self, *(self.lines[0][i] for i in range(self.lines[0].__len__())), **config
@ -226,7 +226,7 @@ class OpenGLParagraph(OpenGLVGroup):
self.lines[1] = [None for _ in range(self.lines[0].__len__())]
for line_no in range(0, self.lines[0].__len__()):
self[line_no].move_to(
self.get_center() + self.lines_initial_positions[line_no]
self.get_center() + self.lines_initial_positions[line_no],
)
return self
@ -255,7 +255,7 @@ class OpenGLParagraph(OpenGLVGroup):
self.lines[1][line_no] = alignment
if self.lines[1][line_no] == "center":
self[line_no].move_to(
np.array([self.get_center()[0], self[line_no].get_center()[1], 0])
np.array([self.get_center()[0], self[line_no].get_center()[1], 0]),
)
elif self.lines[1][line_no] == "right":
self[line_no].move_to(
@ -264,8 +264,8 @@ class OpenGLParagraph(OpenGLVGroup):
self.get_right()[0] - self[line_no].width / 2,
self[line_no].get_center()[1],
0,
]
)
],
),
)
elif self.lines[1][line_no] == "left":
self[line_no].move_to(
@ -274,8 +274,8 @@ class OpenGLParagraph(OpenGLVGroup):
self.get_left()[0] + self[line_no].width / 2,
self[line_no].get_center()[1],
0,
]
)
],
),
)
@ -514,7 +514,7 @@ class OpenGLText(OpenGLSVGMobject):
space.move_to(self.submobjects[submobjects_char_index].get_center())
else:
space.move_to(
self.submobjects[submobjects_char_index - 1].get_center()
self.submobjects[submobjects_char_index - 1].get_center(),
)
chars.add(space)
else:
@ -931,7 +931,7 @@ class OpenGLMarkupText(OpenGLSVGMobject):
colormap = self.extract_color_tags()
if len(colormap) > 0:
logger.warning(
'Using <color> tags in MarkupText is deprecated. Please use <span foreground="..."> instead.'
'Using <color> tags in MarkupText is deprecated. Please use <span foreground="..."> instead.',
)
gradientmap = self.extract_gradient_tags()
@ -939,7 +939,7 @@ class OpenGLMarkupText(OpenGLSVGMobject):
raise ValueError(
f"Pango cannot parse your markup in {self.text}. "
"Please check for typos, unmatched tags or unescaped "
"special chars like < and &."
"special chars like < and &.",
)
if self.line_spacing == -1:
@ -1095,7 +1095,7 @@ class OpenGLMarkupText(OpenGLSVGMobject):
"to": tag.group(2),
"start_offset": start_offset,
"end_offset": end_offset,
}
},
)
self.text = re.sub("<gradient[^>]+>(.+?)</gradient>", r"\1", self.text, 0, re.S)
return gradientmap
@ -1137,7 +1137,7 @@ class OpenGLMarkupText(OpenGLSVGMobject):
"color": tag.group(1),
"start_offset": start_offset,
"end_offset": end_offset,
}
},
)
self.text = re.sub("<color[^>]+>(.+?)</color>", r"\1", self.text, 0, re.S)
return colormap

View file

@ -30,7 +30,8 @@ SVG_DEFAULT_ATTRIBUTES: Dict[str, str] = {
def cascade_element_style(
element: MinidomElement, inherited: Dict[str, str]
element: MinidomElement,
inherited: Dict[str, str],
) -> Dict[str, str]:
"""Collect the element's style attributes based upon both its inheritance and its own attributes.

View file

@ -40,6 +40,7 @@ class SVGMobject(VMobject, metaclass=ConvertToOpenGL):
class Sample(Scene):
def construct(self):
self.play(FadeIn(SVGMobject("manim-logo-sidebar.svg")))
Parameters
--------
file_name : :class:`str`
@ -183,7 +184,9 @@ class SVGMobject(VMobject, metaclass=ConvertToOpenGL):
result += it.chain(
*(
self.get_mobjects_from(
child, style, within_defs=within_defs or is_defs
child,
style,
within_defs=within_defs or is_defs,
)
for child in element.childNodes
)
@ -272,12 +275,14 @@ class SVGMobject(VMobject, metaclass=ConvertToOpenGL):
A float representing the attribute string value.
"""
stripped_attr = "".join(
[char for char in attr if char in string.digits + ".-e"]
[char for char in attr if char in string.digits + ".-e"],
)
return float(stripped_attr)
def use_to_mobjects(
self, use_element: MinidomElement, local_style: Dict
self,
use_element: MinidomElement,
local_style: Dict,
) -> List[VMobject]:
"""Converts a SVG <use> element to a collection of VMobjects.
@ -543,7 +548,8 @@ class SVGMobject(VMobject, metaclass=ConvertToOpenGL):
# TODO: handle rotate, skewX and skewY
# for now adding a warning message
logger.warning(
"Handling of %s transform is not supported yet!", op_name
"Handling of %s transform is not supported yet!",
op_name,
)
def flatten(self, input_list):

View file

@ -121,7 +121,15 @@ def elliptical_arc_to_cubic_bezier(x1, y1, rx, ry, phi, fA, fS, x2, y2):
# Convert from endpoint to center parameterization.
cx, cy, theta1, dtheta = get_elliptical_arc_center_parameters(
x1, y1, rx, ry, phi, fA, fS, x2, y2
x1,
y1,
rx,
ry,
phi,
fA,
fS,
x2,
y2,
)
# For a given arc we should "chop" it up into segments if it is too big
@ -257,7 +265,7 @@ class SVGPathMobject(VMobject, metaclass=ConvertToOpenGL):
zip(
re.findall(pattern, self.path_string),
re.split(pattern, self.path_string)[1:],
)
),
)
# Which mobject should new points be added to
prev_command = None
@ -291,7 +299,10 @@ class SVGPathMobject(VMobject, metaclass=ConvertToOpenGL):
# Produce the (absolute) coordinates of the controls and handles
new_points = self.string_to_points(
command, is_relative, coord_string, start_point
command,
is_relative,
coord_string,
start_point,
)
if command == "M": # moveto
@ -322,7 +333,9 @@ class SVGPathMobject(VMobject, metaclass=ConvertToOpenGL):
for i in range(0, len(new_points), 2):
new_handle = 2 * start_point - prev_handle
self.add_cubic_bezier_curve_to(
new_handle, new_points[i], new_points[i + 1]
new_handle,
new_points[i],
new_points[i + 1],
)
start_point = new_points[i + 1]
prev_handle = new_points[i]

Some files were not shown because too many files have changed in this diff Show more