232 Commits

Author SHA1 Message Date
鹤翔万里
f934bdc61e Merge pull request #1284 from niedong/typo-fix
fix typo docstring in scene_file_writer.py
2020-11-29 19:23:47 +08:00
niedong
ba405521ce fix typo docstring in scene_file_writer.py 2020-11-29 11:51:20 +08:00
鹤翔万里
0dc8e4389d Merge pull request #1268 from niedong/ci-fix
Change Ubuntu version to bionic in .travis.yml
2020-11-14 10:53:25 +08:00
niedong
34ec0f4795 Change Ubuntu version to bionic in .travis.yml
Remove redundant pycairo version
2020-11-09 23:09:38 +08:00
鹤翔万里
faa52d7dd4 Merge pull request #1264 from niedong/fix-ci
Specify pycairo version to 1.19.1
2020-11-08 13:49:35 +08:00
niedong
d797e5f1fe Specify pycairo version to 1.19.1 2020-11-04 18:38:10 +08:00
鹤翔万里
99952067c1 Merge pull request #1260 from Abdul1337/master
Fixed a typo in exapmle_scenes.py
2020-10-21 22:42:20 +08:00
Abdul Aziz
30ae89464e Fixed a typo in exapmle_scenes.py 2020-10-20 18:24:16 +05:30
鹤翔万里
1ecbbbbcd5 Merge pull request #1251 from italosestilon/master
fix iteration through a dictionary
2020-10-10 10:45:52 +08:00
鹤翔万里
186b86cb70 Merge pull request #1250 from amogh7joshi/patch-2
Fix typo in scene.py
2020-10-08 23:09:37 +08:00
Italos Estilon de Souza
4c42083ffc fix iteration through a dictionary 2020-10-07 11:52:05 -03:00
Amogh Joshi
dec753fc26 Update scene.py 2020-10-05 17:49:40 -04:00
鹤翔万里
08c90c272b Merge pull request #1216 from BERENGENITA/patch-1
Fixed typo in comment imports.py
2020-10-02 14:03:07 +08:00
Tony031218
be8b28dd9d update README.md 2020-10-01 10:32:01 +08:00
Tony031218
d0dc7ed301 remove an unnecessary file 2020-10-01 10:12:03 +08:00
鹤翔万里
abc24f2d52 Merge pull request #1147 from MeatBoyed/master
Pygments added to environment.yml
2020-09-30 23:33:08 +08:00
鹤翔万里
53756ea140 Merge pull request #1112 from vivek3141/patch-1
Add dot_color to BulletedList
2020-09-30 23:27:29 +08:00
鹤翔万里
dcb608f258 Merge pull request #1072 from Tony031218/change-coord-color
Allow Axes to change the color of coordinate labels
2020-09-30 23:26:59 +08:00
鹤翔万里
05acf31e47 Merge pull request #1064 from Erik-White/numberline
Correctly return get_unit_size
2020-09-30 23:21:56 +08:00
鹤翔万里
bc5c3968d9 Merge pull request #1043 from kuk0/get_merged_array
remove superfluous code
2020-09-30 23:21:05 +08:00
鹤翔万里
11c451c2e9 Merge pull request #1038 from peninha/patch-1
Corrected a bug in stretch_to_fit_depth function
2020-09-30 23:19:26 +08:00
鹤翔万里
52c5e32ba5 Merge pull request #975 from HappyFacade/patch-1
Update readme to reflect #571
2020-09-30 23:13:16 +08:00
dummy26
37efc93e9c Fix a typo in mobject.py (#847) 2020-09-30 23:03:57 +08:00
鹤翔万里
d63f61b903 Merge pull request #909 from Solara570/numberplane-fix
Small fix to NumberPlane construction
2020-09-30 23:01:49 +08:00
鹤翔万里
49d53d9a8f Merge pull request #836 from mavaras/master
#806 typo in WriteStuff
2020-09-30 22:57:30 +08:00
chaoxiaosu
79bf87754a A solution to 'Latex error converting to dvi' problem (#689) 2020-09-30 22:48:29 +08:00
鹤翔万里
e336cf5ddc Merge pull request #1217 from dor2727/patch-tobytes
fixed deprecation warning: tostring -> tobytes
2020-09-30 22:28:28 +08:00
鹤翔万里
e9638aee2e Merge pull request #1187 from Tony031218/master
A solution to xelatex error converting to xdv
2020-09-30 20:54:47 +08:00
Dor Harpaz
a42d9c6ecb fixed deprecation warning: tostring -> tobytes 2020-08-27 14:03:43 +03:00
BERENGENITA
9f945d9940 Fixed typo in comment imports.py
I have fixed a very simple typo and would like to commit it.
2020-08-27 12:17:43 +02:00
鹤翔万里
7556b99dc0 Update ctex_template.tex 2020-07-28 23:03:59 +08:00
Devin Neal
9174ec335c Update README.md 2020-07-18 09:07:34 -07:00
Charles
ea929d167f Pygments added to environment.yml 2020-06-22 13:06:21 +02:00
Vivek Verma
82d6ad0ef5 Add dot_color to BulletedList 2020-05-28 11:19:08 -07:00
Devin Neal
3c1a6bb8b1 Merge pull request #1091 from applemonkey496/patch-3
Add missing import to brace.py
2020-05-20 20:24:59 -07:00
Devin Neal
00ff47855e Merge pull request #1069 from applemonkey496/patch-1
Fix "itslef" to "itself"
2020-05-20 20:21:10 -07:00
applemonkey496
45c5ec7091 Add missing import to brace.py
Without `import copy` lines 128 to 131 will throw an error. I've tested this edit in my local version of the library and it fixes the bug.
2020-05-20 20:07:13 -07:00
Tony031218
4d78e0c63e fix changing coordinates color 2020-05-15 12:36:55 +08:00
Devin Neal
aff2d21bad Merge pull request #734 from zombie110year/master
latex can't recognize path seperator \\ in windows
2020-05-14 21:13:02 -07:00
applemonkey496
c82b1fc2c9 Fix "itslef" to "itself"
I know this is trivial, but I had to fix it.
2020-05-14 12:42:56 -07:00
Devin Neal
ca0b7a6b06 Merge pull request #1066 from 3b1b/remove-sanim
Remove sanim directory
2020-05-13 23:06:04 -07:00
Devin Neal
d31be357e5 Remove sanim directory 2020-05-13 23:04:31 -07:00
Aathish
a529a59abf Added DocStrings for all methods in Container, Scene, GraphScene, MovingCameraScene, SceneFileWriter, ThreeDScene, SpecialThreeDScene, ZoomedScene, VectorScene, and LinearTransformationScene. (#1040)
* Added DocStrings for methods in Container and Scene.
Removed 2 unused imports from scene.py.

* Added DocStrings for all methods in GraphScene, MovingCameraScene, SceneFileWriter, ThreeDScene, SpecialThreeDScene and ZoomedScene.

* Added DocStrings for all methods in `VectorScene` and LinearTransformationScene...
...except `position_x_coordinate` and `position_y_coordinate`

Co-authored-by: Aathish Sivasubrahmanian <aathishs@Aathishs-MacBook-Air.local>
2020-05-13 22:41:22 -07:00
NavpreetDevpuri
cf656e9c21 Code() in file Code_mobject.py to display code with color highlighted added Paragraph() and "exact_spaces" parameter to Text() (#1036) 2020-05-13 22:19:09 -07:00
NavpreetDevpuri
7f1a15b6ba Fixed ffmpeg 'Impossible to Open' and 'Protocol not found' (#1057) 2020-05-13 22:13:56 -07:00
Erik White
f3f9d0dfb7 Correctly return get_unit_size 2020-05-13 19:15:01 +03:00
Kubo Kovac
2f26a32f96 remove superfluous code 2020-05-10 14:58:01 +02:00
peninha
6a571262fd Corrected a bug in stretch_to_fit_depth function 2020-05-10 01:40:21 -03:00
Devin Neal
dbdd799696 Remove versions from requirements.txt 2020-05-07 11:31:54 -07:00
XiaoYoung
522a5b3c5f Fix space characters problem of Text (#1035)
* Fix Text wrong display

* Fix space characters problem of Text

* Fix a potential bug using height or width in Text

* Update Text

* Fix typo in text_mobject.py
2020-05-07 01:16:39 -07:00
鹤翔万里
3362f93964 Fix three bugs(shaders/stroke/size) of Text Class (text_mobject.py) (#1030)
* fix: remove the last M tag in svg files to make Text run in shaders branch

* fix: close the svg path manually to fix the bug of wrong stroke

* fix: remove Space mobjects in Text to fix the bug of TransformText

* feat: make Text and TextMobject equal in size

* this will lead to more bugs of setting color, so I delete it
2020-05-05 00:12:22 -07:00
Mike Magruder
af65c9d5d4 Performance improvement for most scenes (#974)
tl;dr: this is a significant performance improvement for many scenes. 1.7x - 2.6x improvement in animation it/s.

This is a small change to some of the hotest paths in rendering objects. The biggest win comes from not using np.allclose() to check if two points are close enough. In general, NumPy is awesome at operating on large arrays, but overkill for very tiny questions like this. Created a small function to determine if two points are close using the same algorithm, and limited it to 2D points since that's all we need in set_cairo_context_path().

A couple of other minor tweaks to reduce or eliminate other uses of NumPy in this path.

In general, it is better to avoid wrapping lists in np.array when a real NumPy array isn't actually needed.

Added a new file for performance test scenes, with a single scene from the end of a video I've been working on.

Data:

MacBook Pro (16-inch, 2019)
macOS Catalina 10.15.4
2.4 GHz 8-Core Intel Core i9
64 GB 2667 MHz DDR4
Python 3.7.3 (default, Mar  6 2020, 22:34:30)

Profiler: yappi under Pycharm.

Using the scene Perf1 from the included perf_scenes.py, averaged over 5 runs and rendered with:
manim.py perf_scenes.py Perf1 -pl --leave_progress_bars

Before:
Animation 0: FadeInTextMobject, etc.:               8.93it/s
Animation 1: ShowCreationParametricFunction, etc.: 84.66it/s

Profiler shows 48.5% of the run spent under Camera.set_cairo_context_path()

After
Animation 0: FadeInTextMobject, etc.:               23.45it/s  -- 2.63x improvement
Animation 1: ShowCreationParametricFunction, etc.: 149.62it/s  -- 1.77x improvement

Profiler shows 19.9% of the run spent under Camera.set_cairo_context_path()

Less improvement with production-quality renders, and percent improvement varies with scene of course. This appears to be a good win for every scene I'm working on though. I hope it will be for others, too.

NB: there are more perf improvements to be had, of course, but this is the best one I currently have.
2020-04-24 21:04:08 -07:00
XiaoYoung
f0cdcd90ba Fix Text wrong display (#889) 2020-04-23 20:36:57 -07:00
Devin Neal
19e3c97589 Revise config again (#987) 2020-04-17 02:51:25 -07:00
Devin Neal
811ee4d26b Merge pull request #986 from 3b1b/display-help
Display help if no input file is specified
2020-04-17 02:38:53 -07:00
Devin Neal
c847988e10 Display help if no input file is specified 2020-04-17 02:36:56 -07:00
Devin Neal
1bb2e8c237 Merge pull request #985 from 3b1b/remove-livestream
Remove livestream
2020-04-17 00:08:17 -07:00
Devin Neal
77ab3b8d3a Merge branch 'master' of github.com:3b1b/manim into dev 2020-04-17 00:00:36 -07:00
Devin Neal
87d8671995 Remove livestreaming option 2020-04-16 23:59:22 -07:00
Devin Neal
f0796055cc Update README.md 2020-04-15 20:08:02 -07:00
Happy
93ebd66853 Update readme to reflect #571 2020-04-12 13:07:40 -07:00
Devin Neal
48f2a1ec3c Re-add documentation link 2020-03-13 03:16:59 -07:00
Solara570
99519090fb Small fix to NumberPlane construction 2020-03-08 17:12:38 +08:00
Devin Neal
422e86e0da Remove dead documentation link 2020-02-21 20:28:43 -08:00
Devin Neal
c896f58bbd Merge pull request #877 from azarzadavila/master
Typo in super() 77acc99
2020-02-12 22:38:21 -08:00
azarzadavila
97a0a707d7 Typo in super() 77acc99 2020-02-09 11:31:54 +01:00
Grant Sanderson
30728879be Merge pull request #871 from 3b1b/bayes
Bayes
2020-02-03 09:16:21 -08:00
Grant Sanderson
77acc999cd Rename number_line_config to axis_config 2020-01-15 15:40:30 -08:00
Grant Sanderson
1279f040da Temporarily adding input_file_path to SceneFileWrite config. Not sure why this isn't there already, or if there are problems with setting a default, but it fixed a weird bug that had arisen 2020-01-11 17:14:02 -08:00
Grant Sanderson
0f71b0a408 Playing wiht logo 2020-01-11 17:13:02 -08:00
Grant Sanderson
ada09f1928 Editing old name animations 2020-01-11 17:12:44 -08:00
Grant Sanderson
839fb4ff58 Merge pull request #853 from 3b1b/bayes
Bayes
2020-01-06 09:43:06 -08:00
Grant Sanderson
24d077fbce Change referenced directory of 3b1b content in LICENSE and README 2020-01-06 09:39:33 -08:00
Grant Sanderson
16f8c025cd Small tweaks to old videos when revisiting their animations 2020-01-06 09:38:54 -08:00
Mario Varas
b5a75c3250 #806 typo in WriteStuff 2019-12-23 11:29:19 -05:00
Grant Sanderson
6fe082a5d8 Preliminary end to Bayes project 2019-12-19 19:42:50 -08:00
Grant Sanderson
0e92deddc4 Change ShowSubmobjectsOneByOne defaults 2019-12-19 19:42:28 -08:00
Grant Sanderson
fa2c831ef3 Support UTF8 tex 2019-12-19 19:42:06 -08:00
Grant Sanderson
2916990077 Change from old_projects to from from_3b1b.old 2019-12-17 10:07:37 -08:00
Grant Sanderson
ef6716625e Rename 3b1b_projects to from_3b1b 2019-12-17 09:45:07 -08:00
Grant Sanderson
a138cea3ed Pulled bayes.py into a folder for more bayes projects 2019-12-17 09:40:32 -08:00
Grant Sanderson
1387d88043 Preliminary end to bayes, part 1 2019-12-17 09:39:11 -08:00
Grant Sanderson
9deb2d3732 Change patron end screen 2019-12-17 09:38:18 -08:00
Grant Sanderson
a95318f1ab Fix print_family 2019-12-17 09:37:59 -08:00
Grant Sanderson
5ea6c0f525 Bayes scenes up to GlimpseOfNextVideo 2019-12-15 08:45:40 -08:00
Grant Sanderson
c74cfa3c5d Add error message for ApplyFunction 2019-12-15 08:44:57 -08:00
Grant Sanderson
5cce05fc46 Scenes up to IntroduceLynda 2019-12-12 14:40:42 -08:00
Grant Sanderson
c2838d78a2 Forgot to propagate kwargs in Underline 2019-12-12 14:40:08 -08:00
Grant Sanderson
ba2f2f8840 Merge pull request #829 from 3b1b/bayes
Bayes
2019-12-10 21:47:09 -08:00
Grant Sanderson
ebd4fbd1d2 Halfway through CreateFormulaFromDiagram 2019-12-10 21:36:58 -08:00
Grant Sanderson
b1d8d1081c Merge branch 'master' of github.com:3b1b/manim into bayes 2019-12-10 13:39:48 -08:00
Grant Sanderson
c579fb521e Up to WhenDoesBayesApply in bayes 2019-12-10 13:39:42 -08:00
Grant Sanderson
fc28375e42 Changed modification for tex mobjects that begin with a newline, which involved eliminating alignment when a TexMobject creates many SingleStringTexMobject to figure out how to divvy itself up 2019-12-10 13:39:25 -08:00
Grant Sanderson
f89bb3e125 Added Underline 2019-12-10 13:38:30 -08:00
Grant Sanderson
3628b61d75 Change default color and bubble creation for teacher student scenes 2019-12-10 13:38:18 -08:00
Devin Neal
0bddadea35 Merge pull request #816 from fresnik/master
Documentation typo in constants.rst
2019-12-07 17:52:36 -08:00
Grant Sanderson
cfc5ecc59c First couple scenes of bayes 2019-12-06 17:11:04 -08:00
Grant Sanderson
72006334f5 Added a small fix to the issue of Tex inputs starting with a new line 2019-12-06 17:10:51 -08:00
Grant Sanderson
94a3883880 Remove Mobject.print_family, as that is now in utils.debug 2019-12-06 17:10:26 -08:00
Grant Sanderson
84e7bdb2b1 Added a couple helpful debugging functions 2019-12-06 17:10:00 -08:00
Grant Sanderson
b7cb9aa938 Typo fix 2019-12-05 12:45:01 -08:00
Grant Sanderson
259007954b Merge pull request #820 from 3b1b/projects-reorg
Reorganized files for 3b1b videos into a 3b1b_projects folder
2019-12-05 12:43:06 -08:00
Grant Sanderson
a51a6ab489 Reorganized files for 3b1b videos into a 3b1b_projects folder 2019-12-05 12:41:00 -08:00
Grant Sanderson
e57f08f46e Merge pull request #819 from 3b1b/hyperdarts
Hyperdarts
2019-12-05 12:33:14 -08:00
Grant Sanderson
2e25c4c0a3 Fixed old snow scene 2019-12-05 12:32:20 -08:00
Grant Sanderson
bc593695f9 Fixed old confetti scene 2019-12-05 12:31:53 -08:00
Grant Sanderson
9811564f70 TODO stub 2019-12-05 12:31:23 -08:00
Grant Sanderson
32e4daaeba Typo fix to moduli 2019-12-05 12:31:06 -08:00
Grant Sanderson
aaff13a079 Merge branch 'master' of github.com:3b1b/manim into hyperdarts 2019-12-05 12:30:41 -08:00
Freyr Bergsteinsson
241030f916 Documentation typo in constants.rst, fixes issue #814 2019-12-05 00:23:34 +00:00
Devin Neal
2afa079b6a Merge pull request #780 from timgates42/bugfix/typo_installation
Fix simple typo: installtion -> installation
2019-11-27 23:10:48 -08:00
Devin Neal
637c48905a Merge pull request #805 from mavaras/master
#803 docs typo mistake
2019-11-27 22:56:21 -08:00
mavaras
43098a07e7 #803 docs typo mistake 2019-11-23 10:42:35 -05:00
Grant Sanderson
c37ece9007 Moved hyperdarts to old_projects 2019-11-18 09:29:21 -08:00
Grant Sanderson
aaebd8a5cf End of hyperdarts project 2019-11-18 09:28:58 -08:00
Grant Sanderson
6f70df0852 Animations for hyperdarts up to 7:00 2019-11-12 11:55:37 -08:00
Grant Sanderson
975c4dd03c Explicitly check for None, rather than truthiness, for Axes.get_coordinate_labels 2019-11-12 11:55:19 -08:00
Grant Sanderson
495ace2423 Merge pull request #790 from 3b1b/moduli
Moduli
2019-11-11 14:07:33 -08:00
Grant Sanderson
b651050dd0 Merge branch 'master' of github.com:3b1b/manim into moduli 2019-11-11 14:06:32 -08:00
Grant Sanderson
eb03a56dfc Finished triangle moduli space scene 2019-11-11 14:06:17 -08:00
Grant Sanderson
13193d209e Changed patron name ordering 2019-11-11 14:06:04 -08:00
Devin Neal
bcb8824e2c Merge pull request #698 from Elteoremadebeethoven/master_3b1b
Solve issue add sound in Windows 10
2019-11-06 16:21:58 -08:00
Devin Neal
1e3cf9fa78 Merge pull request #725 from Hammer7/master
Closes: #720
2019-11-06 16:21:23 -08:00
Tim Gates
b1b516e9c4 Fix simple typo: installtion -> installation 2019-10-31 22:38:41 +11:00
Grant Sanderson
0e1da5ef28 Merge pull request #777 from 3b1b/hyperdarts
Hyperdarts
2019-10-28 15:38:09 -07:00
Grant Sanderson
4df666e964 Merge branch 'master' of github.com:3b1b/manim into hyperdarts 2019-10-28 15:35:00 -07:00
Grant Sanderson
0729f2eb59 Retire spirals project 2019-10-28 15:34:55 -07:00
Grant Sanderson
c79474a57c Small changes to the ffmpeg args when writing video files 2019-10-28 14:40:46 -07:00
Devin Neal
ec9dd06d38 Merge pull request #748 from DzyubSpirit/fix-svg-width
Add default stroke width for the svg mobjects
2019-10-26 22:31:25 -07:00
Devin Neal
920d140e40 Merge pull request #776 from MathWhiz/patch-1
README.md fixes
2019-10-26 22:29:36 -07:00
Raymond Arndorfer
b163b1b685 Standardize README.md 2019-10-23 22:58:23 -05:00
Grant Sanderson
8c28017239 Small thumbnail change 2019-10-16 10:38:52 -07:00
Grant Sanderson
e1e66f3082 Merge pull request #752 from 3b1b/hyperdarts
Hyperdarts
2019-10-09 21:33:02 -07:00
Grant Sanderson
c4aefe9396 End of Prime Spiral video 2019-10-09 18:09:15 -07:00
Grant Sanderson
7674a9eaee Changed patreon end screen 2019-10-09 18:09:05 -07:00
DzyubSpirit
76c295a60b Add default stroke width for the svg mobjects
Closes: #747
2019-10-08 10:32:04 +03:00
Grant Sanderson
d80af64798 Many more scenes from the prime spirals video 2019-10-03 13:58:27 -07:00
Grant Sanderson
ccc51664f4 Still being dumb 2019-10-03 13:58:13 -07:00
Grant Sanderson
f66d6e4f97 Added AddTextWordByWord, but it's not yet working, presumably because of some bug in Succession. 2019-10-03 13:58:00 -07:00
Grant Sanderson
67f3d1584c A few filler scenes for spirals project 2019-09-30 12:06:35 -07:00
Grant Sanderson
c94aef8845 Have AnimationGroup initialize its runtime before begin is called. This way it can be composed 2019-09-30 12:06:17 -07:00
Grant Sanderson
4eb6c6fb5b Spiral animations Up to ExplainRays 2019-09-26 11:04:47 -07:00
Grant Sanderson
8e15846ec5 Tiny clean to spacing 2019-09-26 11:04:35 -07:00
Grant Sanderson
ff55e768c9 Spiral animations up to Label44Spirals 2019-09-24 14:40:39 -07:00
Grant Sanderson
557bbff36c Added PGroup 2019-09-24 14:40:21 -07:00
zombie110year
946367aa19 latex can't recognize path seperator \\ in windows
Modify path before transport it to system command
2019-09-24 22:12:22 +08:00
Grant Sanderson
2bb8afa9e0 Animations for the introduction of the prime spiral video 2019-09-19 13:39:02 -07:00
Grant Sanderson
42e0cd07ac Added support for changing and interpolating stroke_width on PMobjects 2019-09-19 13:38:46 -07:00
Grant Sanderson
307ac852a6 Added ShowSubmobjectsOneByOne 2019-09-19 13:38:03 -07:00
Grant Sanderson
ffecd03cb2 Begining of spirals video, which is my newfound distraction 2019-09-18 15:38:27 -07:00
Grant Sanderson
0f037651f3 Small modifications to some old name animations 2019-09-18 15:38:02 -07:00
Grant Sanderson
77797741a5 Small updates to hyperdarts scenes 2019-09-18 15:37:46 -07:00
Hlaing Min
a19a6317ec Closes: #720
Fix to interpret subsequent points of absolute MoveTo (M) command as absolute LineTo (L).
2019-09-13 01:51:22 +08:00
Grant Sanderson
85e5b20ede Small tweak to patron scroll 2019-09-10 13:27:18 -07:00
Grant Sanderson
f34a110d5b More hyperdarts scenes 2019-09-10 13:26:40 -07:00
Grant Sanderson
f54b2ac81a Don't add sound while skipping animations 2019-09-10 13:26:30 -07:00
Grant Sanderson
afbdb94bb3 Set basic functionality to show the hyperdarts game 2019-08-28 14:23:00 -07:00
Grant Sanderson
e85beb91dc Merge pull request #710 from 3b1b/windmill
Windmill
2019-08-27 19:07:23 -07:00
Grant Sanderson
2f2ef09c92 Merge branch 'master' of github.com:3b1b/manim into windmill 2019-08-27 19:05:27 -07:00
Grant Sanderson
a5641c8144 Changed EOC1 Thumbnail 2019-08-27 19:05:15 -07:00
Grant Sanderson
4391c9147b Tweaks to Fourier behavior 2019-08-27 19:05:05 -07:00
Grant Sanderson
308a3e23ad Retiring windmill project 2019-08-27 19:03:36 -07:00
Grant Sanderson
0ac7b420f2 End of windmill project 2019-08-27 19:02:04 -07:00
Alexander Vázquez
32abbb9371 Change way to remove sound_file_path 2019-08-20 01:34:13 -05:00
Devin Neal
b74e5ca254 Merge pull request #680 from xy-23/master
New Text Mobject
2019-08-16 00:58:58 -07:00
xy-23
9b3e60f5ce Update some Text Mobject changes 2019-08-16 15:53:36 +08:00
Devin Neal
f0cff687aa Merge pull request #663 from pranjaldhole/master
conda environment bug fix with pyreadline package, closes #662
2019-08-16 00:37:40 -07:00
Devin Neal
73fea6a197 Merge pull request #668 from jonatasscdc/patch-1
Update requirements.txt
2019-08-16 00:34:38 -07:00
Devin Neal
7e3dbf51fa Merge pull request #672 from omertuc/patch-1
Update requirements.txt to include pyreadline
2019-08-16 00:34:00 -07:00
xy-23
0983fa11be Update some Text Mobject changes 2019-08-12 14:40:42 +08:00
omertuc
d5dc0d4d5b Only install pyreadline on Windows
It's not required on Linux
2019-08-12 05:56:35 +03:00
xy-23
e9fa188d42 New Text Mobject 2019-08-12 09:35:05 +08:00
xy-23
fd3721e050 new Text mobject 2019-08-06 21:05:37 +08:00
omertuc
d61d540655 Update requirements.txt to include pyreadline
This solves #444
2019-08-06 08:19:46 +03:00
Devin Neal
e1c049bece Merge pull request #670 from 0xflotus/patch-1
fixed manim
2019-08-05 14:52:58 -07:00
0xflotus
e498077e6a fixed manim 2019-08-05 23:14:27 +02:00
xy-23
057a92f92c new Text mobject 2019-08-05 22:53:15 +08:00
jonatasscdc
cce2191eb6 Update requirements.txt
updated pycairo version for windows
2019-08-03 14:53:10 -03:00
Grant Sanderson
00b5aaeb26 Animations for windmill up to early draft publish 2019-08-01 10:40:44 -07:00
Pranjal Dhole
91580ed4a3 conda env bug fix- ffmpeg from conda 2019-08-01 17:04:29 +02:00
Pranjal Dhole
06f78bf28f conda environment bug fix with pyreadline package, closes #662 2019-08-01 15:43:30 +02:00
Grant Sanderson
502ad1a02a Further windmill animation, to the end of the problem solution 2019-07-30 16:37:21 -07:00
Devin Neal
49582c3591 Merge pull request #652 from xy-23/master
Fix tqdm display problem in windows
2019-07-29 16:53:17 -07:00
Grant Sanderson
f1413c7717 TryOutSimplestExamples for windmill 2019-07-29 09:54:11 -07:00
Grant Sanderson
55ece141e8 Up to IntroduceWindmill scene 2019-07-26 18:30:11 -07:00
xy-23
519f82f1e7 Fix tqdm display problem in windows 2019-07-26 16:45:52 +08:00
Devin Neal
930e059a16 Merge pull request #651 from xy-23/master
Add a feature
2019-07-26 00:10:22 -07:00
xy-23
82a1b05f28 Add a feature #650 2019-07-26 14:34:21 +08:00
Grant Sanderson
b467444ad3 Beginning of windmill project 2019-07-25 20:05:02 -07:00
Grant Sanderson
c7e6d9d474 Merge pull request #611 from 3b1b/diffyq
Diffyq
2019-07-24 20:38:48 -07:00
Grant Sanderson
d6876b995d tweaking some diffyq content 2019-07-24 20:37:07 -07:00
Grant Sanderson
61bb4944fa Remove borken save_as_gif lines 2019-07-24 20:36:44 -07:00
Devin Neal
9f761822e1 Merge pull request #648 from zavden/master
Fix the list of scenes.py
2019-07-24 16:10:05 -07:00
zavden
3cee3de94f Update extract_scene.py 2019-07-24 18:01:12 -05:00
Devin Neal
38432a73e7 Merge pull request #641 from AamodJ/master
Updated macOS installation
2019-07-20 14:14:00 -07:00
Xiao Young
71b71f2d65 Solution of text rendering problem (#628)
Prevent unwanted space added between TextMobjects
2019-07-20 14:13:23 -07:00
AamodJ
d400952acc Updated macOS installation 2019-07-20 00:49:08 +05:30
Devin Neal
43d28a8595 Merge pull request #632 from tcztzy/master
Arch Linux installation guild
2019-07-13 22:28:00 -07:00
Tang Ziya
17505673d6 remove redundant empty line 2019-07-14 13:11:02 +08:00
Tang Ziya
0fa3415cc0 Arch Linux installation section 2019-07-14 13:06:36 +08:00
Tang Ziya
b31a5fb421 Arch LInux installation guild
Related #629
2019-07-12 21:11:45 +08:00
Devin Neal
eb13def609 update numpy and scipy versions 2019-07-10 17:53:19 -07:00
Devin Neal
a721a19137 Merge pull request #630 from eitanlees/doc-link
DOC: update documentation link in readme
2019-07-10 14:11:19 -07:00
Eitan Lees
25a75f1876 DOC: update documentation link in readme 2019-07-10 13:20:06 -04:00
Devin Neal
b31a174ac6 Merge pull request #622 from npetrangelo/docs
Filled out making_a_scene in the docs
2019-07-07 22:42:08 -07:00
Nathan Petrangelo
612158277e Removed the joke 2019-07-08 01:33:07 -04:00
Nathan Petrangelo
c60dd05e33 Added one more sentence 2019-07-08 01:23:04 -04:00
Nathan Petrangelo
e5d7ebd978 Added code formatting 2019-07-08 01:18:10 -04:00
Nathan Petrangelo
0645bc6acc Filled out making_a_scene overview 2019-07-08 01:13:49 -04:00
Devin Neal
d01ca92120 remove extraneous newline 2019-07-07 21:46:59 -07:00
Devin Neal
61c963a8ae update documentation link again 2019-07-07 21:44:50 -07:00
Devin Neal
e83c69d968 udpate documentation link 2019-07-07 21:37:24 -07:00
Grant Sanderson
36be369901 Beginning diffyq part 5 2019-07-03 11:09:05 -07:00
Grant Sanderson
b3673e93d7 Final animations for Fourier montage video 2019-07-03 11:08:39 -07:00
Grant Sanderson
985ef4518f Bug fix 2019-07-03 11:07:55 -07:00
Grant Sanderson
096f033954 Moved VIDEO_DIR initializations to after MEDIA_DIR 2019-07-01 12:51:48 -07:00
Grant Sanderson
92f4c0c001 Merge branch 'master' of github.com:3b1b/manim into diffyq 2019-06-29 15:21:00 -07:00
Grant Sanderson
10f2c105b1 Final animations for Fourier video 2019-06-29 15:20:52 -07:00
Grant Sanderson
34e343ec66 Changed endscreen default columns 2019-06-29 15:20:00 -07:00
Grant Sanderson
aec56c63be Added LIGHT_PINK 2019-06-29 15:19:43 -07:00
Grant Sanderson
c6d6e500fb Latest scenes for Fourier series video 2019-06-25 09:03:55 -07:00
Grant Sanderson
a3c1640fb7 NumberLine.default_numbers_to_display was not showing topmost number it should have 2019-06-25 09:03:33 -07:00
Grant Sanderson
0a695dd442 Changed Arrow default 2019-06-25 09:02:56 -07:00
Grant Sanderson
64c960041b Latest scenes for Fourier series, up to SimpleComplexExponentExample 2019-06-23 16:26:28 -07:00
Grant Sanderson
f3048eb574 Fixed bug with Bubble 2019-06-23 16:26:05 -07:00
Grant Sanderson
48f38b8940 Line.put_start_and_end_on should return self 2019-06-23 16:25:48 -07:00
Grant Sanderson
a535c6917e Added p2n and n2p abreviations for ComplexPlane 2019-06-23 16:25:22 -07:00
Grant Sanderson
0432514ccf Up to ShowInfiniteSum in diffyq part 4 animations 2019-06-21 17:56:42 -07:00
Grant Sanderson
a9baae4e98 Fixed(?) eye-tracking for PiCreatureScene 2019-06-20 20:23:48 -07:00
Grant Sanderson
0e44abe741 Latest changes for animations of video 4 of diffyq series 2019-06-20 13:26:43 -07:00
Grant Sanderson
40e44e6dd7 Parametric surface should remember what function created it 2019-06-20 13:26:22 -07:00
Grant Sanderson
02413d165a Change ode -> diffyq in imports 2019-06-19 16:24:44 -07:00
286 changed files with 30364 additions and 1312 deletions

1
.gitignore vendored
View File

@@ -7,6 +7,7 @@ cairo_test.py
mayavi_test.py
random_scenes/
files/
assets/
ben_playground.py
ben_cairo_test.py
.floo

View File

@@ -1,5 +1,5 @@
language: python
dist: xenial # required for Python 3.7 (travis-ci/travis-ci#9069)
dist: bionic
python: "3.7"
cache: pip

View File

@@ -1,5 +1,4 @@
All files of this project under the directories active_projects and old_projects
are copyright 3Blue1Brown LLC and used by permission for this project only.
All files of this project under the directory "from_3b1b" are copyright 3Blue1Brown LLC and used by permission for this project only.
Any other file of this project is available under the MIT license as follow:

View File

@@ -1,21 +1,24 @@
<img src="logo/cropped.png"/>
![logo](logo/cropped.png)
[![Build Status](https://travis-ci.org/3b1b/manim.svg?branch=master)](https://travis-ci.org/3b1b/manim)
[![Documentation](https://img.shields.io/badge/docs-EulerTour-blue.svg)](https://www.eulertour.com/learn/manim/)
[![Documentation](https://img.shields.io/badge/docs-EulerTour-blue.svg)](https://www.eulertour.com/docs)
[![MIT License](https://img.shields.io/badge/license-MIT-blue.svg?style=flat)](http://choosealicense.com/licenses/mit/)
[![Manim Subreddit](https://img.shields.io/reddit/subreddit-subscribers/manim.svg?color=ff4301&label=reddit)](https://www.reddit.com/r/manim/)
[![Manim Discord](https://img.shields.io/discord/581738731934056449.svg?label=discord)](https://discord.gg/mMRrZQW)
Manim is an animation engine for explanatory math videos. It's used to create precise animations programmatically, as seen in the videos at [3Blue1Brown](https://www.3blue1brown.com/).
This repository contains the version of manim used by 3Blue1Brown. There is also a community maintained version at https://github.com/ManimCommunity/manim/.
To get help or to join the development effort, please join the [discord](https://discord.gg/mMRrZQW).
## Installation
Manim runs on python 3.7. You can install it from PyPI via pip
Manim runs on Python 3.6 or higher version. You can install it from PyPI via pip:
```sh
pip3 install manimlib
```
System requirements are [cairo](https://www.cairographics.org), [ffmpeg](https://www.ffmpeg.org), [sox](http://sox.sourceforge.net), [latex](https://www.latex-project.org) (optional, if you want to use LaTeX).
System requirements are [cairo](https://www.cairographics.org), [ffmpeg](https://www.ffmpeg.org), [sox](http://sox.sourceforge.net) (optional, if you want to play the prompt tone after running), [latex](https://www.latex-project.org) (optional, if you want to use LaTeX).
You can now use it via the `manim` command. For example:
@@ -23,7 +26,7 @@ You can now use it via the `manim` command. For example:
manim my_project.py MyScene
```
For more options, take a look at the Using manim sections further below.
For more options, take a look at the [Using manim](#using-manim) sections further below.
### Directly
@@ -39,7 +42,7 @@ python3 ./manim.py example_scenes.py SquareToCircle -pl
### Directly (Windows)
1. [Install FFmpeg](https://www.wikihow.com/Install-FFmpeg-on-Windows).
2. Install Cairo. Download the wheel from https://www.lfd.uci.edu/~gohlke/pythonlibs/#pycairo. For most users, ``pycairo1.18.0cp37cp37mwin32.whl`` will do fine.
2. [Install Cairo](https://www.lfd.uci.edu/~gohlke/pythonlibs/#pycairo). For most users, ``pycairo1.18.0cp37cp37mwin32.whl`` will do fine (you can download it or other versions from [here](https://www.lfd.uci.edu/~gohlke/pythonlibs/#pycairo)).
```sh
pip3 install C:\path\to\wheel\pycairo1.18.0cp37cp37mwin32.whl
```
@@ -47,7 +50,7 @@ python3 ./manim.py example_scenes.py SquareToCircle -pl
4. [Install SoX](https://sourceforge.net/projects/sox/files/sox/).
5. Install the remaining Python packages. Make sure that ``pycairo==1.17.1`` is changed to ``pycairo==1.18.0`` in requirements.txt.
5. Install the remaining Python packages.
```sh
git clone https://github.com/3b1b/manim.git
cd manim
@@ -74,14 +77,14 @@ python3 -m manim example_scenes.py SquareToCircle -pl
### Using Docker
Since it's a bit tricky to get all the dependencies set up just right, there is a Dockerfile and Compose file provided in this repo as well as [a premade image on Docker Hub](https://hub.docker.com/r/eulertour/manim/tags/). The Dockerfile contains instructions on how to build a manim image, while the Compose file contains instructions on how to run the image.
The prebuilt container image has manin repository included.
The prebuilt container image has manim repository included.
`INPUT_PATH` is where the container looks for scene files. You must set the `INPUT_PATH`
environment variable to the absolute path containing your scene file and the
`OUTPUT_PATH` environment variable to the directory where you want media to be written.
1. [Install Docker](https://docs.docker.com)
2. [Install Docker Compose](https://docs.docker.com/compose/install/)
3. Render an animation
3. Render an animation:
```sh
INPUT_PATH=/path/to/dir/containing/source/code \
OUTPUT_PATH=/path/to/output/ \
@@ -91,9 +94,9 @@ The command needs to be run as root if your username is not in the docker group.
You can replace `example.scenes.py` with any relative path from your `INPUT_PATH`.
<img src=./manim_docker_diagram.png/>
![docker diagram](./manim_docker_diagram.png)
After running the output will say files ready at `/tmp/output/`, which refers to path inside the container. Your OUTPUT_PATH is bind mounted to this `/tmp/output` so any changes made by the container to `/tmp/output` will be mirrored on your OUTPUT_PATH. `/media/` will be created in `OUTPUT_PATH`.
After running the output will say files ready at `/tmp/output/`, which refers to path inside the container. Your `OUTPUT_PATH` is bind mounted to this `/tmp/output` so any changes made by the container to `/tmp/output` will be mirrored on your `OUTPUT_PATH`. `/media/` will be created in `OUTPUT_PATH`.
`-p` won't work as manim would look for video player in the container system, which it does not have.
@@ -108,49 +111,28 @@ python3 -m manim example_scenes.py SquareToCircle -pl
The `-p` flag in the command above is for previewing, meaning the video file will automatically open when it is done rendering. The `-l` flag is for a faster rendering at a lower quality.
Some other useful flags include:
* `-s` to skip to the end and just show the final frame.
* `-n <number>` to skip ahead to the `n`'th animation of a scene.
* `-f` to show the file in finder (for OSX).
Set `MEDIA_DIR` environment variable to specify where the image and animation files will be written.
Look through the `old_projects` folder to see the code for previous 3b1b videos. Note, however, that developments are often made to the library without considering backwards compatibility with those old projects. To run an old project with a guarantee that it will work, you will have to go back to the commit which completed that project.
Look through the `old_projects` folder to see the code for previous 3b1b videos. Note, however, that developments are often made to the library without considering backwards compatibility with those old projects. To run an old project with a guarantee that it will work, you will have to go back to the commit which completed that project.
While developing a scene, the `-sp` flags are helpful to just see what things look like at the end without having to generate the full animation. It can also be helpful to use the `-n` flag to skip over some number of animations.
While developing a scene, the `-sp` flags are helpful to just see what things look like at the end without having to generate the full animation. It can also be helpful to use the `-n` flag to skip over some number of animations.
### Documentation
Documentation is in progress at [manim.readthedocs.io](https://manim.readthedocs.io).
Documentation is in progress at [eulertour.com/docs](https://www.eulertour.com/docs/). And there is also an all-in-one documentation and tutorials maintained by **@manim-kindergarten**: [manim.ml](https://manim.ml/) (in Chinese).
### Walkthrough
Todd Zimmerman put together a [tutorial](https://talkingphysics.wordpress.com/2019/01/08/getting-started-animating-with-manim-and-python-3-7/) on getting started with manim, which has been updated to run on python 3.7.
### Live Streaming
To live stream your animations, simply run manim with the `--livestream` option.
```sh
> python -m manim --livestream
Writing to media/videos/scene/scene/1080p30/LiveStreamTemp.mp4
Manim is now running in streaming mode. Stream animations by passing
them to manim.play(), e.g.
>>> c = Circle()
>>> manim.play(ShowCreation(c))
>>>
```
It is also possible to stream directly to Twitch. To do that simply pass
--livestream and --to-twitch to manim and specify the stream key with
--with-key. Then when you follow the above example the stream will directly
start on your Twitch channel (with no audio support).
Todd Zimmerman put together a [tutorial](https://talkingphysics.wordpress.com/2019/01/08/getting-started-animating-with-manim-and-python-3-7/) on getting started with manim, which has been updated to run on Python 3.7.
[manim-kindergarten](https://github.com/manim-kindergarten/) wrote and collected some useful extra classes and some codes of videos in [manim_sandbox repo](https://github.com/manim-kindergarten/manim_sandbox).
## Contributing
Is always welcome. In particular, there is a dire need for tests and documentation.
Only accepts pull requests that fixes bugs / fixes typos / improves existing content (for more information, see [#1243](https://github.com/3b1b/manim/issues/1243)). Most pull requests should be directed to the [community version](https://github.com/ManimCommunity/manim/).
## License
All files in the directories active_projects and old_projects, which by and large generate the visuals for 3b1b videos, are copyright 3Blue1Brown.
All files in the directory `from_3b1b`, which by and large generate the visuals for 3b1b videos, are copyright 3Blue1Brown.
The general purpose animation code found in the remainder of the repository, on the other hand, is under the MIT license.

View File

@@ -1,18 +0,0 @@
from active_projects.ode.part4.staging import *
from active_projects.ode.part4.fourier_series_scenes import *
from active_projects.ode.part4.pi_creature_scenes import *
OUTPUT_DIRECTORY = "ode/part4"
SCENES_IN_ORDER = [
ComplexFourierSeriesExample,
ComplexFourierSeriesExampleEnd,
FourierSeriesExampleWithRectForZoom,
ZoomedInFourierSeriesExample,
RelationToOtherVideos,
WhyWouldYouCare,
# Oldies
# FourierSeriesIllustraiton,
# FourierNameIntro,
# CircleAnimationOfF,
]

View File

@@ -1,40 +0,0 @@
#!/usr/bin/env python
from manimlib.imports import *
from active_projects.ode.part2.fourier_series import FourierOfName
name_color_pairs = [
]
circle_counts = [
# 10,
# 25,
100,
]
if __name__ == "__main__":
for name, color in name_color_pairs:
for n_circles in circle_counts:
try:
first_name = name.split(" ")[0]
scene = FourierOfName(
name_text=name,
name_color=color,
n_circles=n_circles,
file_writer_config={
"write_to_movie": True,
"output_directory": os.path.join(
"patron_fourier_names",
first_name,
),
"file_name": "{}_Fouierified_{}_Separate_paths".format(
first_name,
n_circles
),
},
camera_config={
"frame_rate": 24,
},
)
except:
pass

View File

@@ -1,242 +0,0 @@
from manimlib.imports import *
from active_projects.ode.part2.fourier_series import FourierOfTrebleClef
class ComplexFourierSeriesExample(FourierOfTrebleClef):
CONFIG = {
"file_name": "EighthNote",
"run_time": 10,
"n_vectors": 200,
"n_cycles": 2,
"max_circle_stroke_width": 0.75,
"drawing_height": 5,
"center_point": DOWN,
"top_row_y": 3,
"top_row_label_y": 2,
"top_row_x_spacing": 1.75,
"top_row_copy_scale_factor": 0.9,
"start_drawn": False,
}
def construct(self):
self.add_vectors_circles_path()
self.add_top_row(self.vectors, self.circles)
self.write_title()
self.highlight_vectors_one_by_one()
self.change_shape()
def write_title(self):
title = TextMobject("Complex\\\\Fourier series")
title.scale(1.5)
title.to_edge(LEFT)
title.match_y(self.path)
self.wait(5)
self.play(FadeInFromDown(title))
self.wait(2)
self.title = title
def highlight_vectors_one_by_one(self):
# Don't know why these vectors can't get copied.
# That seems like a problem that will come up again.
labels = self.top_row[-1]
next_anims = []
for vector, circle, label in zip(self.vectors, self.circles, labels):
# v_color = vector.get_color()
c_color = circle.get_color()
c_stroke_width = circle.get_stroke_width()
rect = SurroundingRectangle(label, color=PINK)
self.play(
# vector.set_color, PINK,
circle.set_stroke, RED, 3,
FadeIn(rect),
*next_anims
)
self.wait()
next_anims = [
# vector.set_color, v_color,
circle.set_stroke, c_color, c_stroke_width,
FadeOut(rect),
]
self.play(*next_anims)
def change_shape(self):
# path_mob = TexMobject("\\pi")
path_mob = SVGMobject("Nail_And_Gear")
new_path = path_mob.family_members_with_points()[0]
new_path.set_height(4)
new_path.move_to(self.path, DOWN)
new_path.shift(0.5 * UP)
new_coefs = self.get_coefficients_of_path(new_path)
new_vectors = self.get_rotating_vectors(
coefficients=new_coefs
)
new_drawn_path = self.get_drawn_path(new_vectors)
self.vector_clock.set_value(0)
self.vector_clock.suspend_updating(0)
vectors = self.vectors
anims = []
for vect, new_vect in zip(vectors, new_vectors):
new_vect.update()
new_vect.clear_updaters()
line = Line(stroke_width=0)
line.put_start_and_end_on(*vect.get_start_and_end())
anims.append(ApplyMethod(
line.put_start_and_end_on,
*new_vect.get_start_and_end()
))
vect.freq = new_vect.freq
vect.phase = new_vect.phase
vect.coefficient = new_vect.coefficient
vect.line = line
vect.add_updater(
lambda v: v.put_start_and_end_on(
*v.line.get_start_and_end()
)
)
anims += [
FadeOut(self.drawn_path)
]
self.play(*anims, run_time=3)
self.vector_clock.resume_updating()
for vect in self.vectors:
vect.remove_updater(vect.updaters[-1])
self.add(new_drawn_path)
for n in range(self.n_cycles):
self.run_one_cycle()
#
def get_path(self):
path = super().get_path()
path.set_height(self.drawing_height)
path.to_edge(DOWN)
return path
def add_top_row(self, vectors, circles, max_freq=3):
self.top_row = self.get_top_row(
vectors, circles, max_freq
)
self.add(self.top_row)
def get_top_row(self, vectors, circles, max_freq=3):
vector_copies = VGroup()
circle_copies = VGroup()
for vector, circle in zip(vectors, circles):
if vector.freq > max_freq:
break
vcopy = vector.copy()
vcopy.clear_updaters()
ccopy = circle.copy()
ccopy.clear_updaters()
ccopy.original = circle
vcopy.original = vector
vcopy.center_point = np.array([
vector.freq * self.top_row_x_spacing,
self.top_row_y,
0
])
ccopy.center_point = vcopy.center_point
vcopy.add_updater(self.update_top_row_vector_copy)
ccopy.add_updater(self.update_top_row_circle_copy)
vector_copies.add(vcopy)
circle_copies.add(ccopy)
dots = VGroup(*[
TexMobject("\\dots").next_to(
circle_copies, direction,
MED_LARGE_BUFF,
)
for direction in [LEFT, RIGHT]
])
labels = self.get_top_row_labels(vector_copies)
return VGroup(
vector_copies,
circle_copies,
dots,
labels,
)
def update_top_row_vector_copy(self, vcopy):
vcopy.become(vcopy.original)
vcopy.scale(self.top_row_copy_scale_factor)
vcopy.shift(vcopy.center_point - vcopy.get_start())
return vcopy
def update_top_row_circle_copy(self, ccopy):
ccopy.become(ccopy.original)
ccopy.scale(self.top_row_copy_scale_factor)
ccopy.move_to(ccopy.center_point)
return ccopy
def get_top_row_labels(self, vector_copies):
labels = VGroup()
for vector_copy in vector_copies:
freq = vector_copy.freq
label = Integer(freq)
label.move_to(np.array([
freq * self.top_row_x_spacing,
self.top_row_label_y,
0
]))
labels.add(label)
return labels
class ComplexFourierSeriesExampleEnd(ExternallyAnimatedScene):
pass
class FourierSeriesExampleWithRectForZoom(ComplexFourierSeriesExample):
CONFIG = {
"n_vectors": 100,
"slow_factor": 0.01,
"rect_scale_factor": 0.15,
"parametric_function_step_size": 0.0001,
"start_drawn": True,
}
def construct(self):
self.add_vectors_circles_path()
self.circles.set_stroke(opacity=0.5)
rect = self.get_rect()
rect.set_height(self.rect_scale_factor * FRAME_HEIGHT)
rect.add_updater(lambda m: m.move_to(
center_of_mass([
v.get_end()
for v in self.vectors
])
))
self.add(rect)
self.run_one_cycle()
def get_rect(self):
return ScreenRectangle(
color=WHITE,
stroke_width=2,
)
class ZoomedInFourierSeriesExample(FourierSeriesExampleWithRectForZoom, MovingCameraScene):
CONFIG = {
"vector_config": {
"max_tip_length_to_length_ratio": 0.15,
"tip_length": 0.05,
}
}
def setup(self):
ComplexFourierSeriesExample.setup(self)
MovingCameraScene.setup(self)
def get_rect(self):
return self.camera_frame

View File

@@ -1,22 +0,0 @@
from manimlib.imports import *
class WhyWouldYouCare(TeacherStudentsScene):
def construct(self):
self.student_says(
"Who cares!",
target_mode="sassy",
student_index=2,
added_anims=[self.teacher.change, "guilty"],
)
self.wait()
self.play(
RemovePiCreatureBubble(self.students[2]),
self.teacher.change, "raise_right_hand",
self.get_student_changes(
"pondering", "erm", "thinking",
look_at_arg=self.screen,
)
)
self.look_at(self.screen)
self.wait(5)

View File

@@ -18,7 +18,7 @@ Directories
Created under ``MEDIA_DIR`` by default.
TEX_DIR
Files written by Latex are stored here. It also acts as a cache
so that the files aren't rewritten each Latex is needed.
so that the files aren't rewritten each time Latex is needed.
Those directories are created if they don't exist.

View File

@@ -1,4 +1,15 @@
Making a Scene
==============
Talk about Scenes and organization, bring it all together.
A scene is what renders when manim is executed. Each scene contains mobjects, which can then be animated as
previously explained. In code, a scene is a class that extends ``Scene`` and implements the ``construct``
function, like so. Manim will execute this function to render the scene.
.. code-block:: python
:linenos:
from manimlib.imports import *
class ExampleScene(Scene):
def construct(self):
# Add and animate mobjects here

View File

@@ -39,3 +39,26 @@ the ``activate`` binary by doing ``source bin/activate``, to exit use the ``deac
texlive texlive-latex-extra texlive-fonts-extra
texlive-latex-recommended texlive-science texlive-fonts-extra tipa
Arch Linux
----------
Install system libraries::
# pacman -S cairo ffmpeg opencv sox
Install Latex distribution::
# pacman -S texlive-most
OR install python-manimlib_:sup:`AUR` package::
$ git clone https://aur.archlinux.org/python-manimlib.git
$ cd python-manimlib
$ makepkg -si
You can use AUR helpers such as yay_:sup:`AUR`::
$ yay -S python-manimlib
.. _python-manimlib: https://aur.archlinux.org/packages/python-manimlib/
.. _yay: https://aur.archlinux.org/packages/yay/

View File

@@ -8,5 +8,5 @@ Mac come preinstalled with python2, but to use manim, python3 is required
2. Install Cairo: ``brew install cairo``
3. Install Sox: ``brew install sox``
4. Install ffmpeg: ``brew install ffmpeg``
5. Install latex (MiKTeX): https://miktex.org/howto/install-miktex-mac
5. Install latex (MacTeX): ``brew cask install mactex``
6. Install manimlib ``pip install manimlib`` (or ``pip install --user manimlib`` to just yourself)

View File

@@ -49,12 +49,12 @@ the repository page with ``Clone or download`` button and unzip it.
Open the commandline within the manim directory with ``Shift + Right click`` on an empty space in the folder and select ``open command window here``
Install manim python dependencies with ``pip install -r requirement.txt``
Install manim python dependencies with ``pip install -r requirements.txt``
Test the installation
---------------------
Type in ``python -m manim -h`` and if nothing went wrong during the installtion process you should see the help text.
Type in ``python -m manim -h`` and if nothing went wrong during the installation process you should see the help text.
Use ``python -m manim example_scenes.py SquareToCircle -pl`` to render the example scene and the file should play after rendering. The movie file should be
in ``media/videos/example_scenes/480p15``

View File

@@ -5,7 +5,7 @@ channels:
dependencies:
- python=3.7
- cairo
- ffmpeg
- ffmpeg
- colour==0.1.5
- numpy==1.15.0
- pillow==5.2.0
@@ -14,4 +14,7 @@ dependencies:
- opencv==3.4.2
- pycairo==1.18.0
- pydub==0.23.0
- pyreadline
- ffmpeg
- pygments==2.6.1
- pip:
- pyreadline

View File

@@ -5,7 +5,7 @@ from manimlib.imports import *
# To watch one of these scenes, run the following:
# python -m manim example_scenes.py SquareToCircle -pl
#
# Use the flat -l for a faster rendering at a lower
# Use the flag -l for a faster rendering at a lower
# quality.
# Use -s to skip to the end and just save the final frame
# Use the -p to have the animation (or image, if -s was
@@ -98,7 +98,7 @@ class WarpSquare(Scene):
class WriteStuff(Scene):
def construct(self):
example_text = TextMobject(
"This is a some text",
"This is some text",
tex_to_color_map={"text": YELLOW}
)
example_tex = TexMobject(

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,10 +1,10 @@
from active_projects.ode.part1.pendulum import *
from active_projects.ode.part1.staging import *
from active_projects.ode.part1.pi_scenes import *
from active_projects.ode.part1.phase_space import *
from active_projects.ode.part1.wordy_scenes import *
from active_projects.diffyq.part1.pendulum import *
from active_projects.diffyq.part1.staging import *
from active_projects.diffyq.part1.pi_scenes import *
from active_projects.diffyq.part1.phase_space import *
from active_projects.diffyq.part1.wordy_scenes import *
OUTPUT_DIRECTORY = "ode/part1"
OUTPUT_DIRECTORY = "diffyq/part1"
SCENES_IN_ORDER = [
WhenChangeIsEasier,
VectorFieldTest,

View File

@@ -1,10 +1,10 @@
from active_projects.ode.part2.staging import *
from active_projects.ode.part2.fourier_series import *
from active_projects.ode.part2.heat_equation import *
from active_projects.ode.part2.pi_scenes import *
from active_projects.ode.part2.wordy_scenes import *
from active_projects.diffyq.part2.staging import *
from active_projects.diffyq.part2.fourier_series import *
from active_projects.diffyq.part2.heat_equation import *
from active_projects.diffyq.part2.pi_scenes import *
from active_projects.diffyq.part2.wordy_scenes import *
OUTPUT_DIRECTORY = "ode/part2"
OUTPUT_DIRECTORY = "diffyq/part2"
SCENES_IN_ORDER = [
PartTwoOfTour,
HeatEquationIntroTitle,

View File

@@ -1,11 +1,11 @@
from active_projects.ode.part3.staging import *
from active_projects.ode.part3.temperature_graphs import *
from active_projects.ode.part3.pi_creature_scenes import *
from active_projects.ode.part3.wordy_scenes import *
from active_projects.ode.part3.discrete_case import *
from active_projects.diffyq.part3.staging import *
from active_projects.diffyq.part3.temperature_graphs import *
from active_projects.diffyq.part3.pi_creature_scenes import *
from active_projects.diffyq.part3.wordy_scenes import *
from active_projects.diffyq.part3.discrete_case import *
OUTPUT_DIRECTORY = "ode/part3"
OUTPUT_DIRECTORY = "diffyq/part3"
SCENES_IN_ORDER = [
LastChapterWrapper,
ThreeConstraints,

View File

@@ -0,0 +1,65 @@
from active_projects.diffyq.part4.staging import *
from active_projects.diffyq.part4.fourier_series_scenes import *
from active_projects.diffyq.part4.pi_creature_scenes import *
from active_projects.diffyq.part4.three_d_graphs import *
from active_projects.diffyq.part4.temperature_scenes import *
from active_projects.diffyq.part4.complex_functions import *
from active_projects.diffyq.part4.long_fourier_scenes import *
from active_projects.diffyq.part3.staging import *
OUTPUT_DIRECTORY = "diffyq/part4"
SCENES_IN_ORDER = [
ComplexFourierSeriesExample,
FourierOfFourier,
FourierOfFourierZoomedIn,
FourierOfFourier100xZoom,
FourierSeriesFormula,
RelationToOtherVideos,
WhyWouldYouCare,
ShowLinearity,
CombineSeveralSolutions,
FourierGainsImmortality,
SolveForWavesNothingElse,
CycleThroughManyLinearCombinations,
StepFunctionExample,
WhichWavesAreAvailable,
AlternateBoundaryConditions,
AskQuestionOfGraph,
CommentOnFouriersImmortality,
HangOnThere,
ShowInfiniteSum,
TechnicalNuances,
BreakDownStepFunction,
StepFunctionSolutionFormla,
# How to compute
FourierSeriesOfLineIllustration,
GeneralizeToComplexFunctions,
ClarifyInputAndOutput,
GraphForFlattenedPi,
PiFourierSeries,
RealValuedFunctionFourierSeries,
YouSaidThisWasEasier,
AskAboutComplexNotVector,
SimpleComplexExponentExample,
LooseWithLanguage,
DemonstrateAddingArrows,
TRangingFrom0To1,
LabelRotatingVectors,
IntegralTrick,
SwapIntegralAndSum,
FootnoteOnSwappingIntegralAndSum,
FormulaOutOfContext,
ShowRangeOfCnFormulas,
DescribeSVG,
# TODO
IncreaseOrderOfApproximation,
ShowStepFunctionIn2dView,
StepFunctionIntegral,
GeneralChallenge,
# Oldies
# FourierSeriesIllustraiton,
# FourierNameIntro,
# CircleAnimationOfF,
]

View File

@@ -0,0 +1,5 @@
from active_projects.diffyq.part5.staging import *
OUTPUT_DIRECTORY = "diffyq/part5"
SCENES_IN_ORDER = [
]

View File

@@ -0,0 +1,23 @@
from active_projects.diffyq.part4.long_fourier_scenes import *
OUTPUT_DIRECTORY = "diffyq/part4"
SCENES_IN_ORDER = [
ZoomedInFourierSeriesExample,
FourierSeriesExampleWithRectForZoom,
ZoomedInFourierSeriesExample100x,
FourierOfFourier100xZoom,
FourierOfFourierZoomedIn,
FourierOfFourier,
SigmaZoomedInFourierSeriesExample,
SigmaFourierSeriesExampleWithRectForZoom,
NailAndGearZoomedInFourierSeriesExample,
NailAndGearFourierSeriesExampleWithRectForZoom,
TrebleClefZoomedInFourierSeriesExample,
TrebleClefFourierSeriesExampleWithRectForZoom,
FourierOfSeattle,
FourierOfSeattleZoomedIn,
FourierOfBritain,
FourierOfBritainZoomedIn,
FourierOfHilbert,
FourierOfHilbertZoomedIn,
]

View File

@@ -1,5 +1,5 @@
from manimlib.imports import *
from active_projects.ode.part1.shared_constructs import *
from active_projects.diffyq.part1.shared_constructs import *
class Pendulum(VGroup):
@@ -254,7 +254,7 @@ class ThetaVsTAxes(Axes):
"tick_frequency": PI / 8,
"unit_size": 1.5,
},
"number_line_config": {
"axis_config": {
"color": "#EEEEEE",
"stroke_width": 2,
"include_tip": False,
@@ -371,7 +371,7 @@ class IntroducePendulum(PiCreatureScene, MovingCameraScene):
"tip_length": 0.3,
},
"x_max": 12,
"number_line_config": {
"axis_config": {
"stroke_width": 2,
}
},
@@ -750,7 +750,7 @@ class LowAnglePendulum(Scene):
"number_scale_val": 0.5,
},
"x_max": 25,
"number_line_config": {
"axis_config": {
"tip_length": 0.3,
"stroke_width": 2,
}
@@ -837,7 +837,7 @@ class MediumAnglePendulum(LowAnglePendulum):
"y_axis_config": {"unit_size": 0.75},
"y_max": PI / 2,
"y_min": -PI / 2,
"number_line_config": {
"axis_config": {
"tip_length": 0.3,
"stroke_width": 2,
}
@@ -867,7 +867,7 @@ class HighAnglePendulum(LowAnglePendulum):
"y_axis_config": {"unit_size": 0.5},
"y_max": PI,
"y_min": -PI,
"number_line_config": {
"axis_config": {
"tip_length": 0.3,
"stroke_width": 2,
}
@@ -888,7 +888,7 @@ class VeryLowAnglePendulum(LowAnglePendulum):
"y_axis_config": {"unit_size": 2},
"y_max": PI / 4,
"y_min": -PI / 4,
"number_line_config": {
"axis_config": {
"tip_length": 0.3,
"stroke_width": 2,
}

View File

@@ -1,6 +1,6 @@
from manimlib.imports import *
from active_projects.ode.part1.shared_constructs import *
from active_projects.ode.part1.pendulum import Pendulum
from active_projects.diffyq.part1.shared_constructs import *
from active_projects.diffyq.part1.pendulum import Pendulum
# TODO: Arguably separate the part showing many
@@ -2012,11 +2012,18 @@ class ManyStepsFromDifferentStartingPoints(TakeManyTinySteps):
class Thumbnail(IntroduceVectorField):
CONFIG = {
"vector_field_config": {
"delta_x": 0.5,
"delta_y": 0.5,
# "delta_x": 0.5,
# "delta_y": 0.5,
# "max_magnitude": 5,
# "length_func": lambda norm: 0.5 * sigmoid(norm),
"delta_x": 1,
"delta_y": 1,
"max_magnitude": 5,
"length_func": lambda norm: 0.5 * sigmoid(norm),
}
"length_func": lambda norm: 0.9 * sigmoid(norm),
},
"big_pendulum_config": {
"damping": 0.4,
},
}
def construct(self):
@@ -2027,7 +2034,7 @@ class Thumbnail(IntroduceVectorField):
field = self.vector_field
field.set_stroke(width=5)
for vector in field:
vector.set_stroke(width=3)
vector.set_stroke(width=8)
vector.tip.set_stroke(width=0)
vector.tip.scale(1.5, about_point=vector.get_last_point())
vector.set_opacity(1)
@@ -2063,17 +2070,43 @@ class Thumbnail(IntroduceVectorField):
new_mob.set_stroke(width=0)
black_parts.add(new_mob)
for vect in field:
for mob in title.family_members_with_points():
for p in [vect.get_start(), vect.get_end()]:
x, y = p[:2]
x0, y0 = mob.get_corner(DL)[:2]
x1, y1 = mob.get_corner(UR)[:2]
if x0 < x < x1 and y0 < y < y1:
vect.set_opacity(0.25)
vect.tip.set_stroke(width=0)
# for vect in field:
# for mob in title.family_members_with_points():
# for p in [vect.get_start(), vect.get_end()]:
# x, y = p[:2]
# x0, y0 = mob.get_corner(DL)[:2]
# x1, y1 = mob.get_corner(UR)[:2]
# if x0 < x < x1 and y0 < y < y1:
# vect.set_opacity(0.25)
# vect.tip.set_stroke(width=0)
self.add(self.plane)
self.add(field)
self.add(black_parts)
self.add(title)
# self.add(black_parts)
# self.add(title)
self.add_line(self.plane)
def add_line(self, axes):
func = self.vector_field_func
line = VMobject()
line.start_new_path(axes.c2p(-TAU, 3.5))
dt = 0.1
t = 0
total_time = 40
while t < total_time:
t += dt
last_point = line.get_last_point()
new_point = last_point + dt * func(last_point)
if new_point[0] > FRAME_WIDTH / 2:
new_point = last_point + FRAME_WIDTH * LEFT
line.start_new_path(new_point)
else:
line.add_smooth_curve_to(new_point)
line.set_stroke(WHITE, 6)
line.make_smooth()
self.add(line)

View File

@@ -1,5 +1,5 @@
from manimlib.imports import *
from active_projects.ode.part1.shared_constructs import *
from active_projects.diffyq.part1.shared_constructs import *
class SomeOfYouWatching(TeacherStudentsScene):

View File

@@ -1,10 +1,10 @@
from manimlib.imports import *
from active_projects.ode.part1.shared_constructs import *
from active_projects.ode.part1.pendulum import Pendulum
from active_projects.ode.part1.pendulum import ThetaVsTAxes
from active_projects.ode.part1.phase_space import IntroduceVectorField
from old_projects.div_curl import PhaseSpaceOfPopulationModel
from old_projects.div_curl import ShowTwoPopulations
from active_projects.diffyq.part1.shared_constructs import *
from active_projects.diffyq.part1.pendulum import Pendulum
from active_projects.diffyq.part1.pendulum import ThetaVsTAxes
from active_projects.diffyq.part1.phase_space import IntroduceVectorField
from from_3b1b.old.div_curl import PhaseSpaceOfPopulationModel
from from_3b1b.old.div_curl import ShowTwoPopulations
# Scenes

View File

@@ -1,5 +1,5 @@
from manimlib.imports import *
from active_projects.ode.part1.shared_constructs import *
from active_projects.diffyq.part1.shared_constructs import *
class SmallAngleApproximationTex(Scene):

View File

@@ -29,6 +29,8 @@ class FourierCirclesScene(Scene):
"slow_factor": 0.25,
"center_point": ORIGIN,
"parametric_function_step_size": 0.001,
"drawn_path_color": YELLOW,
"drawn_path_stroke_width": 2,
}
def setup(self):
@@ -95,7 +97,6 @@ class FourierCirclesScene(Scene):
phase = np.log(coefficient).imag
vector.rotate(phase, about_point=ORIGIN)
vector.freq = freq
vector.phase = phase
vector.coefficient = coefficient
vector.center_func = center_func
vector.add_updater(self.update_vector)
@@ -103,12 +104,13 @@ class FourierCirclesScene(Scene):
def update_vector(self, vector, dt):
time = self.get_vector_time()
vector.set_angle(
vector.phase + time * vector.freq * TAU
)
vector.shift(
vector.center_func() - vector.get_start()
)
coef = vector.coefficient
freq = vector.freq
phase = np.log(coef).imag
vector.set_length(abs(coef))
vector.set_angle(phase + time * freq * TAU)
vector.shift(vector.center_func() - vector.get_start())
return vector
def get_circles(self, vectors):
@@ -155,14 +157,19 @@ class FourierCirclesScene(Scene):
return path
# TODO, this should be a general animated mobect
def get_drawn_path(self, vectors, stroke_width=2, **kwargs):
def get_drawn_path_alpha(self):
return self.get_vector_time()
def get_drawn_path(self, vectors, stroke_width=None, **kwargs):
if stroke_width is None:
stroke_width = self.drawn_path_stroke_width
path = self.get_vector_sum_path(vectors, **kwargs)
broken_path = CurvesAsSubmobjects(path)
broken_path.curr_time = 0
def update_path(path, dt):
# alpha = path.curr_time * self.get_slow_factor()
alpha = self.get_vector_time()
alpha = self.get_drawn_path_alpha()
n_curves = len(path)
for a, sp in zip(np.linspace(0, 1, n_curves), path):
b = alpha - a
@@ -174,7 +181,7 @@ class FourierCirclesScene(Scene):
path.curr_time += dt
return path
broken_path.set_color(YELLOW)
broken_path.set_color(self.drawn_path_color)
broken_path.add_updater(update_path)
return broken_path
@@ -365,48 +372,74 @@ class FourierOfPiSymbol(FourierCirclesScene):
return path
class FourierOfName(FourierOfPiSymbol):
class FourierOfTexPaths(FourierOfPiSymbol, MovingCameraScene):
CONFIG = {
"n_vectors": 100,
"name_color": WHITE,
"name_text": "Abc",
"animated_name": "Abc",
"time_per_symbol": 5,
"slow_factor": 1 / 5,
"parametric_function_step_size": 0.01,
}
def construct(self):
name = TextMobject(self.name_text)
name = TextMobject(self.animated_name)
max_width = FRAME_WIDTH - 2
max_height = FRAME_HEIGHT - 2
name.set_width(max_width)
if name.get_height() > max_height:
name.set_height(max_height)
frame = self.camera.frame
frame.save_state()
vectors = VGroup(VectorizedPoint())
circles = VGroup(VectorizedPoint())
for path in name.family_members_with_points():
for subpath in path.get_subpaths():
sp_mob = VMobject()
sp_mob.set_points(subpath)
coefs = self.get_coefficients_of_path(sp_mob)
new_circles = self.get_circles(
new_vectors = self.get_rotating_vectors(
coefficients=coefs
)
new_circles = self.get_circles(new_vectors)
self.set_decreasing_stroke_widths(new_circles)
drawn_path = self.get_drawn_path(new_circles)
drawn_path = self.get_drawn_path(new_vectors)
drawn_path.clear_updaters()
drawn_path.set_stroke(self.name_color, 3)
new_circles.suspend_updating()
self.play(ReplacementTransform(circles, new_circles))
new_circles.resume_updating()
circles = new_circles
static_vectors = VMobject().become(new_vectors)
static_circles = VMobject().become(new_circles)
# static_circles = new_circles.deepcopy()
# static_vectors.clear_updaters()
# static_circles.clear_updaters()
self.play(
Transform(vectors, static_vectors, remover=True),
Transform(circles, static_circles, remover=True),
frame.set_height, 1.5 * name.get_height(),
frame.move_to, path,
)
self.add(new_vectors, new_circles)
self.vector_clock.set_value(0)
self.play(
ShowCreation(drawn_path),
rate_func=linear,
run_time=self.time_per_symbol
)
circles.suspend_updating()
self.play(FadeOut(circles))
self.remove(new_vectors, new_circles)
self.add(static_vectors, static_circles)
vectors = static_vectors
circles = static_circles
self.play(
FadeOut(vectors),
Restore(frame),
run_time=2
)
self.wait(3)

View File

@@ -1,5 +1,5 @@
from manimlib.imports import *
from active_projects.ode.part2.shared_constructs import *
from active_projects.diffyq.part2.shared_constructs import *
class TwoDBodyWithManyTemperatures(ThreeDScene):
@@ -164,8 +164,12 @@ class BringTwoRodsTogether(Scene):
"tick_frequency": 10,
},
},
"y_labels": range(20, 100, 20),
"graph_x_min": 0,
"graph_x_max": 10,
"midpoint": 5,
"max_temp": 90,
"min_temp": 10,
"wait_time": 30,
"default_n_rod_pieces": 20,
"alpha": 1.0,
@@ -187,9 +191,7 @@ class BringTwoRodsTogether(Scene):
y_label.to_edge(UP)
axes.y_axis.label = y_label
axes.y_axis.add(y_label)
axes.y_axis.add_numbers(
*range(20, 100, 20)
)
axes.y_axis.add_numbers(*self.y_labels)
self.axes = axes
self.y_label = y_label
@@ -200,7 +202,7 @@ class BringTwoRodsTogether(Scene):
x_min=self.graph_x_min,
x_max=self.graph_x_max,
step_size=self.step_size,
discontinuities=[5],
discontinuities=[self.midpoint],
)
graph.color_using_background_image("VerticalTempGradient")
@@ -315,20 +317,27 @@ class BringTwoRodsTogether(Scene):
rods.add_updater(self.update_rods)
self.play(
ClockPassesTime(
self.clock,
run_time=self.wait_time,
hours_passed=self.wait_time,
),
self.get_clock_anim(self.wait_time),
FadeOut(labels)
)
#
def get_clock_anim(self, time, **kwargs):
config = {
"run_time": time,
"hours_passed": time,
}
config.update(kwargs)
return ClockPassesTime(self.clock, **config)
def initial_function(self, x):
if x <= 5:
return 90
epsilon = 1e-10
if x < self.midpoint - epsilon:
return self.max_temp
elif x > self.midpoint + epsilon:
return self.min_temp
else:
return 10
return (self.min_temp + self.max_temp) / 2
def update_graph(self, graph, dt, alpha=None, n_mini_steps=500):
if alpha is None:
@@ -432,7 +441,10 @@ class BringTwoRodsTogether(Scene):
)
def y_to_color(self, y):
return temperature_to_color((y - 45) / 45)
y_max = self.max_temp
y_min = self.min_temp
alpha = inverse_interpolate(y_min, y_max, y)
return temperature_to_color(interpolate(-0.8, 0.8, alpha))
def rod_point_to_color(self, point):
return self.y_to_color(

View File

@@ -1,5 +1,5 @@
from manimlib.imports import *
from active_projects.ode.part2.wordy_scenes import WriteHeatEquationTemplate
from active_projects.diffyq.part2.wordy_scenes import WriteHeatEquationTemplate
class ReactionsToInitialHeatEquation(PiCreatureScene):

View File

@@ -1,5 +1,5 @@
from manimlib.imports import *
from active_projects.ode.part1.staging import TourOfDifferentialEquations
from active_projects.diffyq.part1.staging import TourOfDifferentialEquations
class PartTwoOfTour(TourOfDifferentialEquations):
@@ -210,7 +210,7 @@ class BlackScholes(AltBrownianMotion):
self.wait(self.wait_time)
def add_title(self):
title = TextMobject("Black-Sholes equations")
title = TextMobject("Black-Scholes equations")
title.scale(1.5)
title.next_to(2 * UP, UP)
@@ -235,7 +235,7 @@ class BlackScholes(AltBrownianMotion):
x_max=20,
y_min=0,
y_max=10,
number_line_config={
axis_config={
"unit_size": 0.5,
},
)

View File

@@ -1,5 +1,5 @@
from manimlib.imports import *
from active_projects.ode.part2.heat_equation import *
from active_projects.diffyq.part2.heat_equation import *
class ShowNewRuleAtDiscreteBoundary(DiscreteSetup):

View File

@@ -1,5 +1,5 @@
from manimlib.imports import *
from active_projects.ode.part2.wordy_scenes import *
from active_projects.diffyq.part2.wordy_scenes import *
class IveHeardOfThis(TeacherStudentsScene):

View File

@@ -1,6 +1,6 @@
from manimlib.imports import *
from active_projects.ode.part2.fourier_series import FourierOfTrebleClef
from active_projects.diffyq.part2.fourier_series import FourierOfTrebleClef
class FourierNameIntro(Scene):
@@ -234,7 +234,7 @@ class FourierSeriesIllustraiton(Scene):
CONFIG = {
"n_range": range(1, 31, 2),
"axes_config": {
"number_line_config": {
"axis_config": {
"include_tip": False,
},
"x_axis_config": {
@@ -245,42 +245,20 @@ class FourierSeriesIllustraiton(Scene):
"x_max": 1,
"y_min": -1,
"y_max": 1,
}
},
"colors": [BLUE, GREEN, RED, YELLOW, PINK],
}
def construct(self):
n_range = self.n_range
aaa_group = self.get_axes_arrow_axes()
aaa_group.shift(2 * UP)
aaa_group.shift_onto_screen()
axes1, arrow, axes2 = aaa_group
axes1 = Axes(**self.axes_config)
axes1.x_axis.add_numbers(
0.5, 1,
number_config={"num_decimal_places": 1}
)
axes2 = axes1.copy()
target_func_graph = self.get_target_func_graph(axes2)
axes2.add(target_func_graph)
axes2.add(self.get_target_func_graph(axes2))
arrow = Arrow(LEFT, RIGHT, color=WHITE)
group = VGroup(axes1, arrow, axes2)
group.arrange(RIGHT, buff=LARGE_BUFF)
group.shift(2 * UP)
group.shift_onto_screen()
sine_graphs = VGroup(*[
axes1.get_graph(self.generate_nth_func(n))
for n in n_range
])
sine_graphs.set_stroke(width=3)
sine_graphs.set_color_by_gradient(
BLUE, GREEN, RED, YELLOW, PINK,
BLUE, GREEN, RED, YELLOW, PINK,
)
partial_sums = VGroup(*[
axes1.get_graph(self.generate_kth_partial_sum_func(k + 1))
for k in range(len(n_range))
])
partial_sums.match_style(sine_graphs)
sine_graphs = self.get_sine_graphs(axes1)
partial_sums = self.get_partial_sums(axes1, sine_graphs)
sum_tex = self.get_sum_tex()
sum_tex.next_to(axes1, DOWN, LARGE_BUFF)
@@ -311,7 +289,6 @@ class FourierSeriesIllustraiton(Scene):
)
self.add(axes1, arrow, axes2)
self.add(target_func_graph)
self.add(sum_tex, eq, target_func_tex)
self.add(range_words)
@@ -340,6 +317,42 @@ class FourierSeriesIllustraiton(Scene):
self.play(*anims2)
curr_partial_sum = partial_sum
def get_axes_arrow_axes(self):
axes1 = Axes(**self.axes_config)
axes1.x_axis.add_numbers(
0.5, 1,
number_config={"num_decimal_places": 1}
)
axes1.y_axis.add_numbers(
-1, 1,
number_config={"num_decimal_places": 1},
direction=LEFT,
)
axes2 = axes1.deepcopy()
arrow = Arrow(LEFT, RIGHT, color=WHITE)
group = VGroup(axes1, arrow, axes2)
group.arrange(RIGHT, buff=MED_LARGE_BUFF)
return group
def get_sine_graphs(self, axes):
sine_graphs = VGroup(*[
axes.get_graph(self.generate_nth_func(n))
for n in self.n_range
])
sine_graphs.set_stroke(width=3)
for graph, color in zip(sine_graphs, it.cycle(self.colors)):
graph.set_color(color)
return sine_graphs
def get_partial_sums(self, axes, sine_graphs):
partial_sums = VGroup(*[
axes.get_graph(self.generate_kth_partial_sum_func(k + 1))
for k in range(len(self.n_range))
])
partial_sums.match_style(sine_graphs)
return partial_sums
def get_sum_tex(self):
return TexMobject(
"\\frac{4}{\\pi} \\left(",

View File

@@ -1,7 +1,7 @@
from scipy import integrate
from manimlib.imports import *
from active_projects.ode.part2.heat_equation import *
from active_projects.diffyq.part2.heat_equation import *
class TemperatureGraphScene(SpecialThreeDScene):
@@ -137,19 +137,19 @@ class TemperatureGraphScene(SpecialThreeDScene):
def get_surface(self, axes, func, **kwargs):
config = {
"u_min": axes.x_min,
"u_max": axes.x_max,
"v_min": axes.y_min,
"v_max": axes.y_max,
"u_min": axes.y_min,
"u_max": axes.y_max,
"v_min": axes.x_min,
"v_max": axes.x_max,
"resolution": (
(axes.x_max - axes.x_min) // axes.x_axis.tick_frequency,
(axes.y_max - axes.y_min) // axes.y_axis.tick_frequency,
(axes.x_max - axes.x_min) // axes.x_axis.tick_frequency,
),
}
config.update(self.default_surface_config)
config.update(kwargs)
return ParametricSurface(
lambda x, t: axes.c2p(
lambda t, x: axes.c2p(
x, t, func(x, t)
),
**config
@@ -181,13 +181,12 @@ class TemperatureGraphScene(SpecialThreeDScene):
fill_color=WHITE,
fill_opacity=0.2
)
plane.add_updater(lambda m: m.move_to(
plane.add_updater(lambda m: m.shift(
axes.c2p(
axes.x_min,
t_tracker.get_value(),
axes.z_min,
),
IN + LEFT,
) - plane.points[0]
))
plane.t_tracker = t_tracker
return plane
@@ -380,6 +379,10 @@ class BreakDownAFunction(SimpleCosExpGraph):
"z_min": -2,
"y_max": 20,
},
"low_axes_config": {
"z_min": -3,
"z_axis_config": {"unit_size": 1}
},
"n_low_axes": 4,
"k": 0.2,
}
@@ -403,10 +406,7 @@ class BreakDownAFunction(SimpleCosExpGraph):
top_axes.center()
top_axes.to_edge(UP)
low_axes = self.get_three_d_axes(
z_min=-3,
z_axis_config={"unit_size": 1}
)
low_axes = self.get_three_d_axes(**self.low_axes_config)
low_axes.y_axis.set_opacity(0)
for axis in low_axes:
axis.label.fade(1)

View File

@@ -1,5 +1,5 @@
from manimlib.imports import *
from active_projects.ode.part2.wordy_scenes import *
from active_projects.diffyq.part2.wordy_scenes import *
class ThreeMainObservations(Scene):

View File

@@ -0,0 +1,712 @@
from manimlib.imports import *
class GeneralizeToComplexFunctions(Scene):
CONFIG = {
"axes_config": {
"x_min": 0,
"x_max": 10,
"x_axis_config": {
"stroke_width": 2,
},
"y_min": -2.5,
"y_max": 2.5,
"y_axis_config": {
"tick_frequency": 0.25,
"unit_size": 1.5,
"include_tip": False,
"stroke_width": 2,
},
},
"complex_plane_config": {
"axis_config": {
"unit_size": 2
}
},
}
def construct(self):
self.show_cosine_wave()
self.transition_to_complex_plane()
self.add_rotating_vectors_making_cos()
def show_cosine_wave(self):
axes = Axes(**self.axes_config)
axes.shift(2 * LEFT - axes.c2p(0, 0))
y_axis = axes.y_axis
y_labels = y_axis.get_number_mobjects(
*range(-2, 3),
number_config={"num_decimal_places": 1},
)
t_tracker = ValueTracker(0)
t_tracker.add_updater(lambda t, dt: t.increment_value(dt))
get_t = t_tracker.get_value
def func(x):
return 2 * np.cos(x)
cos_x_max = 20
cos_wave = axes.get_graph(func, x_max=cos_x_max)
cos_wave.set_color(YELLOW)
shown_cos_wave = cos_wave.copy()
shown_cos_wave.add_updater(
lambda m: m.pointwise_become_partial(
cos_wave, 0,
np.clip(get_t() / cos_x_max, 0, 1),
),
)
dot = Dot()
dot.set_color(PINK)
dot.add_updater(lambda d: d.move_to(
y_axis.n2p(func(get_t())),
))
h_line = always_redraw(lambda: Line(
dot.get_right(),
shown_cos_wave.get_end(),
stroke_width=1,
))
real_words = TextMobject(
"Real number\\\\output"
)
real_words.to_edge(LEFT)
real_words.shift(2 * UP)
real_arrow = Arrow()
real_arrow.add_updater(
lambda m: m.put_start_and_end_on(
real_words.get_corner(DR),
dot.get_center(),
).scale(0.9),
)
self.add(t_tracker)
self.add(axes)
self.add(y_labels)
self.add(shown_cos_wave)
self.add(dot)
self.add(h_line)
self.wait(2)
self.play(
FadeInFrom(real_words, RIGHT),
FadeIn(real_arrow),
)
self.wait(5)
y_axis.generate_target()
y_axis.target.rotate(-90 * DEGREES)
y_axis.target.center()
y_axis.target.scale(2 / 1.5)
y_labels.generate_target()
for label in y_labels.target:
label.next_to(
y_axis.target.n2p(label.get_value()),
DOWN, MED_SMALL_BUFF,
)
self.play(
FadeOut(shown_cos_wave),
FadeOut(axes.x_axis),
FadeOut(h_line),
)
self.play(
MoveToTarget(y_axis),
MoveToTarget(y_labels),
real_words.shift, 2 * RIGHT + UP,
)
self.wait()
self.y_axis = y_axis
self.y_labels = y_labels
self.real_words = real_words
self.real_arrow = real_arrow
self.dot = dot
self.t_tracker = t_tracker
def transition_to_complex_plane(self):
y_axis = self.y_axis
y_labels = self.y_labels
plane = self.get_complex_plane()
plane_words = plane.label
self.add(plane, *self.get_mobjects())
self.play(
FadeOut(y_labels),
FadeOut(y_axis),
ShowCreation(plane),
)
self.play(Write(plane_words))
self.wait()
self.plane = plane
self.plane_words = plane_words
def add_rotating_vectors_making_cos(self):
plane = self.plane
real_words = self.real_words
real_arrow = self.real_arrow
t_tracker = self.t_tracker
get_t = t_tracker.get_value
v1 = Vector(2 * RIGHT)
v2 = Vector(2 * RIGHT)
v1.set_color(BLUE)
v2.set_color(interpolate_color(GREY_BROWN, WHITE, 0.5))
v1.add_updater(
lambda v: v.set_angle(get_t())
)
v2.add_updater(
lambda v: v.set_angle(-get_t())
)
v1.add_updater(
lambda v: v.shift(plane.n2p(0) - v.get_start())
)
# Change?
v2.add_updater(
lambda v: v.shift(plane.n2p(0) - v.get_start())
)
ghost_v1 = v1.copy()
ghost_v1.set_opacity(0.5)
ghost_v1.add_updater(
lambda v: v.shift(
v2.get_end() - v.get_start()
)
)
ghost_v2 = v2.copy()
ghost_v2.set_opacity(0.5)
ghost_v2.add_updater(
lambda v: v.shift(
v1.get_end() - v.get_start()
)
)
circle = Circle(color=GREY_BROWN)
circle.set_stroke(width=1)
circle.set_width(2 * v1.get_length())
circle.move_to(plane.n2p(0))
formula = TexMobject(
# "\\cos(x) ="
# "{1 \\over 2}e^{ix} +"
# "{1 \\over 2}e^{-ix}",
"2\\cos(x) =",
"e^{ix}", "+", "e^{-ix}",
tex_to_color_map={
"e^{ix}": v1.get_color(),
"e^{-ix}": v2.get_color(),
}
)
formula.next_to(ORIGIN, UP, buff=0.75)
# formula.add_background_rectangle()
formula.set_stroke(BLACK, 3, background=True)
formula.to_edge(LEFT, buff=MED_SMALL_BUFF)
formula_brace = Brace(formula[1:], UP)
formula_words = formula_brace.get_text(
"Sum of\\\\rotations"
)
formula_words.set_stroke(BLACK, 3, background=True)
randy = Randolph()
randy.to_corner(DL)
randy.look_at(formula)
self.play(
FadeOut(real_words),
FadeOut(real_arrow),
)
self.play(
FadeIn(v1),
FadeIn(v2),
FadeIn(circle),
FadeIn(ghost_v1),
FadeIn(ghost_v2),
)
self.wait(3)
self.play(FadeInFromDown(formula))
self.play(
GrowFromCenter(formula_brace),
FadeIn(formula_words),
)
self.wait(2)
self.play(FadeIn(randy))
self.play(randy.change, "pleading")
self.play(Blink(randy))
self.wait()
self.play(randy.change, "confused")
self.play(Blink(randy))
self.wait()
self.play(FadeOut(randy))
self.wait(20)
#
def get_complex_plane(self):
plane = ComplexPlane(**self.complex_plane_config)
plane.add_coordinates()
plane.label = TextMobject("Complex plane")
plane.label.scale(1.5)
plane.label.to_corner(UR, buff=MED_SMALL_BUFF)
return plane
class ClarifyInputAndOutput(GeneralizeToComplexFunctions):
CONFIG = {
"input_space_rect_config": {
"stroke_color": WHITE,
"stroke_width": 1,
"fill_color": DARKER_GREY,
"fill_opacity": 1,
"width": 6,
"height": 2,
},
}
def construct(self):
self.setup_plane()
self.setup_input_space()
self.setup_input_trackers()
self.describe_input()
self.describe_output()
def setup_plane(self):
plane = self.get_complex_plane()
plane.sublabel = TextMobject("(Output space)")
plane.sublabel.add_background_rectangle()
plane.sublabel.next_to(plane.label, DOWN)
self.add(plane, plane.label)
self.plane = plane
def setup_input_space(self):
rect = Rectangle(**self.input_space_rect_config)
rect.to_corner(UL, buff=SMALL_BUFF)
input_line = self.get_input_line(rect)
input_words = TextMobject("Input space")
input_words.next_to(
rect.get_bottom(), UP,
SMALL_BUFF,
)
self.add(rect)
self.add(input_line)
self.input_rect = rect
self.input_line = input_line
self.input_words = input_words
def setup_input_trackers(self):
plane = self.plane
input_line = self.input_line
input_tracker = ValueTracker(0)
get_input = input_tracker.get_value
input_dot = Dot()
input_dot.set_color(PINK)
f_always(
input_dot.move_to,
lambda: input_line.n2p(get_input())
)
input_decimal = DecimalNumber()
input_decimal.scale(0.7)
always(input_decimal.next_to, input_dot, UP)
f_always(input_decimal.set_value, get_input)
path = self.get_path()
def get_output_point():
return path.point_from_proportion(
get_input()
)
output_dot = Dot()
output_dot.match_style(input_dot)
f_always(output_dot.move_to, get_output_point)
output_vector = Vector()
output_vector.set_color(WHITE)
output_vector.add_updater(
lambda v: v.put_start_and_end_on(
plane.n2p(0),
get_output_point()
)
)
output_decimal = DecimalNumber()
output_decimal.scale(0.7)
always(output_decimal.next_to, output_dot, UR, SMALL_BUFF)
f_always(
output_decimal.set_value,
lambda: plane.p2n(get_output_point()),
)
self.input_tracker = input_tracker
self.input_dot = input_dot
self.input_decimal = input_decimal
self.path = path
self.output_dot = output_dot
self.output_vector = output_vector
self.output_decimal = output_decimal
def describe_input(self):
input_tracker = self.input_tracker
self.play(FadeInFrom(self.input_words, UP))
self.play(
FadeInFromLarge(self.input_dot),
FadeIn(self.input_decimal),
)
for value in 1, 0:
self.play(
input_tracker.set_value, value,
run_time=2
)
self.wait()
def describe_output(self):
path = self.path
output_dot = self.output_dot
output_decimal = self.output_decimal
input_dot = self.input_dot
input_tracker = self.input_tracker
plane = self.plane
real_line = plane.x_axis.copy()
real_line.set_stroke(RED, 4)
real_words = TextMobject("Real number line")
real_words.next_to(ORIGIN, UP)
real_words.to_edge(RIGHT)
traced_path = TracedPath(output_dot.get_center)
traced_path.match_style(path)
self.play(
ShowCreation(real_line),
FadeInFrom(real_words, DOWN)
)
self.play(
FadeOut(real_line),
FadeOut(real_words),
)
self.play(
FadeInFrom(plane.sublabel, UP)
)
self.play(
FadeIn(output_decimal),
TransformFromCopy(input_dot, output_dot),
)
kw = {
"run_time": 10,
"rate_func": lambda t: smooth(t, 1),
}
self.play(
ApplyMethod(input_tracker.set_value, 1, **kw),
ShowCreation(path.copy(), remover=True, **kw),
)
self.add(path)
self.add(output_dot)
self.wait()
# Flatten to 1d
real_function_word = TextMobject(
"Real-valued function"
)
real_function_word.next_to(ORIGIN, DOWN, MED_LARGE_BUFF)
path.generate_target()
path.target.stretch(0, 1)
path.target.move_to(plane.n2p(0))
self.play(
FadeIn(real_function_word),
MoveToTarget(path),
)
input_tracker.set_value(0)
self.play(
input_tracker.set_value, 1,
**kw
)
#
def get_input_line(self, input_rect):
input_line = UnitInterval()
input_line.move_to(input_rect)
input_line.shift(0.25 * UP)
input_line.set_width(
input_rect.get_width() - 1
)
input_line.add_numbers(0, 0.5, 1)
return input_line
def get_path(self):
# mob = SVGMobject("BatmanLogo")
mob = TexMobject("\\pi")
path = mob.family_members_with_points()[0]
path.set_height(3.5)
path.move_to(2 * DOWN, DOWN)
path.set_stroke(YELLOW, 2)
path.set_fill(opacity=0)
return path
class GraphForFlattenedPi(ClarifyInputAndOutput):
CONFIG = {
"camera_config": {"background_color": DARKER_GREY},
}
def construct(self):
self.setup_plane()
plane = self.plane
self.remove(plane, plane.label)
path = self.get_path()
axes = Axes(
x_min=0,
x_max=1,
x_axis_config={
"unit_size": 7,
"include_tip": False,
"tick_frequency": 0.1,
},
y_min=-1.5,
y_max=1.5,
y_axis_config={
"include_tip": False,
"unit_size": 2.5,
"tick_frequency": 0.5,
},
)
axes.set_width(FRAME_WIDTH - 1)
axes.set_height(FRAME_HEIGHT - 1, stretch=True)
axes.center()
axes.x_axis.add_numbers(
0.5, 1.0,
number_config={"num_decimal_places": 1},
)
axes.y_axis.add_numbers(
-1.0, 1.0,
number_config={"num_decimal_places": 1},
)
def func(t):
return plane.x_axis.p2n(
path.point_from_proportion(t)
)
graph = axes.get_graph(func)
graph.set_color(PINK)
v_line = always_redraw(lambda: Line(
axes.x_axis.n2p(axes.x_axis.p2n(graph.get_end())),
graph.get_end(),
stroke_width=1,
))
self.add(axes)
self.add(v_line)
kw = {
"run_time": 10,
"rate_func": lambda t: smooth(t, 1),
}
self.play(ShowCreation(graph, **kw))
self.wait()
class SimpleComplexExponentExample(ClarifyInputAndOutput):
CONFIG = {
"input_space_rect_config": {
"width": 14,
"height": 1.5,
},
"input_line_config": {
"unit_size": 0.5,
"x_min": 0,
"x_max": 25,
"stroke_width": 2,
},
"input_numbers": range(0, 30, 5),
"input_tex_args": ["t", "="],
}
def construct(self):
self.setup_plane()
self.setup_input_space()
self.setup_input_trackers()
self.setup_output_trackers()
# Testing
time = self.input_line.x_max
self.play(
self.input_tracker.set_value, time,
run_time=time,
rate_func=linear,
)
def setup_plane(self):
plane = ComplexPlane()
plane.scale(2)
plane.add_coordinates()
plane.shift(DOWN)
self.plane = plane
self.add(plane)
def setup_input_trackers(self):
input_line = self.input_line
input_tracker = ValueTracker(0)
get_input = input_tracker.get_value
input_tip = ArrowTip(start_angle=-TAU / 4)
input_tip.scale(0.5)
input_tip.set_color(PINK)
f_always(
input_tip.move_to,
lambda: input_line.n2p(get_input()),
lambda: DOWN,
)
input_label = VGroup(
TexMobject(*self.input_tex_args),
DecimalNumber(),
)
input_label[0].set_color_by_tex("t", PINK)
input_label.scale(0.7)
input_label.add_updater(
lambda m: m.arrange(RIGHT, buff=SMALL_BUFF)
)
input_label.add_updater(
lambda m: m[1].set_value(get_input())
)
input_label.add_updater(
lambda m: m.next_to(input_tip, UP, SMALL_BUFF)
)
self.input_tracker = input_tracker
self.input_tip = input_tip
self.input_label = input_label
self.add(input_tip, input_label)
def setup_output_trackers(self):
plane = self.plane
get_input = self.input_tracker.get_value
def get_output():
return np.exp(complex(0, get_input()))
def get_output_point():
return plane.n2p(get_output())
output_label, static_output_label = [
TexMobject(
"e^{i t}" + s,
tex_to_color_map={"t": PINK},
background_stroke_width=3,
)
for s in ["", "\\approx"]
]
output_label.scale(1.2)
output_label.add_updater(
lambda m: m.shift(
-m.get_bottom() +
get_output_point() +
rotate_vector(
0.35 * RIGHT,
get_input(),
)
)
)
output_vector = Vector()
output_vector.set_opacity(0.75)
output_vector.add_updater(
lambda m: m.put_start_and_end_on(
plane.n2p(0), get_output_point(),
)
)
t_max = 40
full_output_path = ParametricFunction(
lambda t: plane.n2p(np.exp(complex(0, t))),
t_min=0,
t_max=t_max
)
output_path = VMobject()
output_path.set_stroke(YELLOW, 2)
output_path.add_updater(
lambda m: m.pointwise_become_partial(
full_output_path,
0, get_input() / t_max,
)
)
static_output_label.next_to(plane.c2p(1, 1), UR)
output_decimal = DecimalNumber(
include_sign=True,
)
output_decimal.scale(0.8)
output_decimal.set_stroke(BLACK, 3, background=True)
output_decimal.add_updater(
lambda m: m.set_value(get_output())
)
output_decimal.add_updater(
lambda m: m.next_to(
static_output_label,
RIGHT, 2 * SMALL_BUFF,
aligned_edge=DOWN,
)
)
self.add(output_path)
self.add(output_vector)
self.add(output_label)
self.add(static_output_label)
self.add(BackgroundRectangle(output_decimal))
self.add(output_decimal)
#
def get_input_line(self, input_rect):
input_line = NumberLine(**self.input_line_config)
input_line.move_to(input_rect)
input_line.set_width(
input_rect.get_width() - 1.5,
stretch=True,
)
input_line.add_numbers(*self.input_numbers)
return input_line
class TRangingFrom0To1(SimpleComplexExponentExample):
CONFIG = {
"input_space_rect_config": {
"width": 6,
"height": 2,
},
}
def construct(self):
self.setup_input_space()
self.setup_input_trackers()
self.play(
self.input_tracker.set_value, 1,
run_time=10,
rate_func=linear
)
def get_input_line(self, rect):
result = ClarifyInputAndOutput.get_input_line(self, rect)
result.stretch(0.9, 0)
result.set_stroke(width=2)
for sm in result.get_family():
if isinstance(sm, DecimalNumber):
sm.stretch(1 / 0.9, 0)
sm.set_stroke(width=0)
return result

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,242 @@
from manimlib.imports import *
from active_projects.diffyq.part4.fourier_series_scenes import ComplexFourierSeriesExample
from manimlib.once_useful_constructs.fractals import HilbertCurve
class FourierSeriesExampleWithRectForZoom(ComplexFourierSeriesExample):
CONFIG = {
"n_vectors": 100,
"slow_factor": 0.01,
"rect_scale_factor": 0.1,
"start_drawn": True,
"drawing_height": 7,
"rect_stroke_width": 1,
}
def construct(self):
self.add_vectors_circles_path()
self.circles.set_stroke(opacity=0.5)
rect = self.rect = self.get_rect()
rect.set_height(self.rect_scale_factor * FRAME_HEIGHT)
rect.add_updater(lambda m: m.move_to(
self.get_rect_center()
))
self.add(rect)
self.run_one_cycle()
def get_rect_center(self):
return center_of_mass([
v.get_end()
for v in self.vectors
])
def get_rect(self):
return ScreenRectangle(
color=BLUE,
stroke_width=self.rect_stroke_width,
)
class ZoomedInFourierSeriesExample(FourierSeriesExampleWithRectForZoom, MovingCameraScene):
CONFIG = {
"vector_config": {
"max_tip_length_to_length_ratio": 0.15,
"tip_length": 0.05,
},
"parametric_function_step_size": 0.001,
}
def setup(self):
ComplexFourierSeriesExample.setup(self)
MovingCameraScene.setup(self)
def get_rect(self):
return self.camera_frame
def add_vectors_circles_path(self):
super().add_vectors_circles_path()
for v in self.vectors:
if v.get_stroke_width() < 1:
v.set_stroke(width=1)
class ZoomedInFourierSeriesExample100x(ZoomedInFourierSeriesExample):
CONFIG = {
"vector_config": {
"max_tip_length_to_length_ratio": 0.15 * 0.4,
"tip_length": 0.05 * 0.2,
"max_stroke_width_to_length_ratio": 80,
"stroke_width": 3,
},
"max_circle_stroke_width": 0.5,
"rect_scale_factor": 0.01,
# "parametric_function_step_size": 0.01,
}
def get_rect_center(self):
return self.vectors[-1].get_end()
# def get_drawn_path(self, vectors, stroke_width=2, **kwargs):
# return self.get_path_end(vectors, stroke_width, **kwargs)
class TrebleClefFourierSeriesExampleWithRectForZoom(FourierSeriesExampleWithRectForZoom):
CONFIG = {
"file_name": "TrebleClef",
"drawn_path_stroke_width": 10,
}
class TrebleClefZoomedInFourierSeriesExample(ZoomedInFourierSeriesExample):
CONFIG = {
"file_name": "TrebleClef",
}
class NailAndGearFourierSeriesExampleWithRectForZoom(FourierSeriesExampleWithRectForZoom):
CONFIG = {
"file_name": "Nail_And_Gear",
"n_vectors": 200,
"drawn_path_color": "#39FF14",
}
class NailAndGearZoomedInFourierSeriesExample(ZoomedInFourierSeriesExample):
CONFIG = {
"file_name": "Nail_And_Gear",
"n_vectors": 200,
"drawn_path_color": "#39FF14",
}
class SigmaFourierSeriesExampleWithRectForZoom(FourierSeriesExampleWithRectForZoom):
CONFIG = {
"n_vectors": 200,
"drawn_path_color": PINK,
"rect_stroke_width": 0,
}
def get_shape(self):
return TexMobject("\\Sigma")
class SigmaZoomedInFourierSeriesExample(SigmaFourierSeriesExampleWithRectForZoom, ZoomedInFourierSeriesExample):
pass
class FourierOfFourier(FourierSeriesExampleWithRectForZoom):
CONFIG = {
"file_name": "FourierOneLine",
"n_vectors": 300,
"rect_stroke_width": 1,
}
class FourierOfFourierZoomedIn(ZoomedInFourierSeriesExample):
CONFIG = {
"file_name": "FourierOneLine",
"max_circle_stroke_width": 0.3,
"n_vectors": 300,
}
class FourierOfFourier100xZoom(ZoomedInFourierSeriesExample100x):
CONFIG = {
"file_name": "FourierOneLine",
"max_circle_stroke_width": 0.3,
"n_vectors": 300,
"slow_factor": 0.001,
}
def run_one_cycle(self):
self.vector_clock.set_value(0.3)
self.wait(40)
class FourierOfHilbert(FourierSeriesExampleWithRectForZoom):
CONFIG = {
"n_vectors": 300,
"rect_stroke_width": 1,
"drawn_path_stroke_width": 4,
"drawn_path_color": BLUE,
}
def get_path(self):
path = HilbertCurve(order=5)
path.set_height(self.drawing_height)
path.to_edge(DOWN)
combined_path = VMobject()
for sm in path.family_members_with_points():
combined_path.append_vectorized_mobject(sm)
start = combined_path.get_start()
end = combined_path.get_end()
points = [
interpolate(end, start, alpha)
for alpha in np.linspace(0, 1, 10)
]
for point in points:
combined_path.add_line_to(point)
combined_path.set_stroke(width=0)
return combined_path
class FourierOfHilbertZoomedIn(FourierOfHilbert, ZoomedInFourierSeriesExample):
pass
class FourierOfBritain(FourierSeriesExampleWithRectForZoom):
CONFIG = {
"file_name": "Britain",
"n_vectors": 500,
"drawn_path_color": RED,
}
class FourierOfBritainZoomedIn(FourierOfBritain, ZoomedInFourierSeriesExample):
pass
class FourierOfSeattle(FourierSeriesExampleWithRectForZoom):
CONFIG = {
"file_name": "SeattleSkyline",
"drawing_height": 7,
"n_vectors": 400,
"drawn_path_color": TEAL,
"drawn_path_stroke_width": 5,
}
class FourierOfSeattleZoomedIn(ZoomedInFourierSeriesExample):
CONFIG = {
"file_name": "SeattleSkyline",
"drawing_height": 7,
"n_vectors": 400,
"drawn_path_color": TEAL,
"drawn_path_stroke_width": 5,
"max_circle_stroke_width": 0.3,
}
class VideoWrapper(Scene):
def construct(self):
fade_rect = FullScreenFadeRectangle()
fade_rect.set_fill(DARK_GREY, 1)
screen_rect = ScreenRectangle()
screen_rect.set_height(4)
screen_rect.set_fill(BLACK, 1)
screen_rect.set_stroke(width=0)
boundary = AnimatedBoundary(screen_rect)
title = TextMobject("Learn the math")
title.scale(1.5)
title.next_to(screen_rect, UP)
self.add(fade_rect)
self.add(screen_rect)
self.add(boundary)
self.play(FadeInFromDown(title))
self.wait(19)

View File

@@ -0,0 +1,235 @@
from manimlib.imports import *
class WhyWouldYouCare(TeacherStudentsScene):
def construct(self):
self.student_says(
"Who cares!",
target_mode="sassy",
student_index=2,
added_anims=[self.teacher.change, "guilty"],
)
self.wait()
self.play(
RemovePiCreatureBubble(self.students[2]),
self.teacher.change, "raise_right_hand",
self.get_student_changes(
"pondering", "erm", "thinking",
look_at_arg=self.screen,
)
)
self.look_at(self.screen)
self.wait(5)
class SolveForWavesNothingElse(TeacherStudentsScene):
def construct(self):
self.student_says(
"Sure, we can\\\\solve it for\\\\sums of waves...",
target_mode="sassy",
student_index=2,
added_anims=[self.teacher.change, "guilty"]
)
self.change_student_modes("pondering", "pondering", "sassy")
self.look_at(self.screen)
self.wait(4)
self.student_says(
"But nothing else!",
target_mode="angry",
)
self.change_student_modes(
"concerned_musician",
"concerned_musician",
"angry",
)
self.wait(5)
class HangOnThere(TeacherStudentsScene):
def construct(self):
student = self.students[2]
axes1 = Axes(
x_min=0,
x_max=1,
y_min=-1.5,
y_max=1.5,
x_axis_config={
"tick_frequency": 0.25,
"include_tip": False,
"unit_size": 3,
},
y_axis_config={
"tick_frequency": 0.5,
"include_tip": False,
},
)
axes1.set_stroke(width=2)
axes2 = axes1.deepcopy()
neq = TexMobject("\\neq")
neq.scale(2)
group = VGroup(axes1, neq, axes2)
group.arrange(RIGHT)
group.set_height(4)
group.next_to(
student.get_corner(UL), UP,
buff=LARGE_BUFF,
)
step_graph = axes1.get_graph(
lambda x: (1 if x < 0.5 else -1),
discontinuities=[0.5],
)
step_graph.set_color(YELLOW)
wave_graphs = VGroup(*[
axes2.get_graph(
lambda x: (4 / PI) * np.sum([
(u / n) * np.cos(n * PI * x)
for u, n in zip(
it.cycle([1, -1]),
range(1, max_n, 2),
)
]),
)
for max_n in range(3, 103, 2)
])
wave_graphs.set_stroke(width=3)
wave_graphs.set_color_by_gradient(WHITE, PINK)
last_wave_graph = wave_graphs[-1]
last_wave_graph.set_stroke(PINK, 2)
wave_graphs.remove(last_wave_graph)
# wave_graphs[-1].set_stroke(width=3)
# wave_graphs[-1].set_stroke(BLACK, 5, background=True)
group.add(step_graph)
self.student_says(
"Hang on\\\\hang on\\\\hang on...",
target_mode="surprised",
content_introduction_class=FadeIn,
student_index=2,
added_anims=[
self.teacher.change, "guilty"
],
run_time=1,
)
self.wait()
self.play(
RemovePiCreatureBubble(
student,
target_mode="raise_left_hand",
look_at_arg=group,
),
FadeInFromDown(group),
)
last_wg = VectorizedPoint()
n_first_fades = 4
for wg in wave_graphs[:n_first_fades]:
self.play(
last_wg.set_stroke, {"width": 0.1},
FadeIn(wg),
)
last_wg = wg
self.play(
LaggedStart(
*[
UpdateFromAlphaFunc(
wg,
lambda m, a: m.set_stroke(
width=(3 * there_and_back(a) + 0.1 * a)
),
)
for wg in wave_graphs[n_first_fades:]
],
run_time=5,
lag_ratio=0.2,
),
ApplyMethod(
last_wg.set_stroke, {"width": 0.1},
run_time=0.25,
),
FadeIn(
last_wave_graph,
rate_func=squish_rate_func(smooth, 0.9, 1),
run_time=5,
),
self.teacher.change, "thinking",
)
self.change_student_modes(
"confused", "confused", "angry"
)
self.wait(3)
class YouSaidThisWasEasier(TeacherStudentsScene):
def construct(self):
self.change_all_student_modes(
"confused", look_at_arg=self.screen,
)
self.student_says(
"I'm sorry, you said\\\\this was easier?",
target_mode="sassy"
)
self.play(self.teacher.change, "guilty")
self.wait(3)
self.teacher_says(
"Bear with\\\\me",
bubble_kwargs={"height": 3, "width": 3},
)
self.look_at(self.screen)
self.wait(3)
class LooseWithLanguage(TeacherStudentsScene):
def construct(self):
terms = VGroup(
TextMobject("``Complex number''"),
TextMobject("``Vector''"),
)
colors = [YELLOW, BLUE]
for term, color in zip(terms, colors):
term.set_color(color)
terms.scale(1.5)
terms.arrange(DOWN, buff=LARGE_BUFF)
terms.to_edge(UP)
terms.match_x(self.students)
self.teacher_says(
"Loose with\\\\language",
bubble_kwargs={"width": 3, "height": 3},
run_time=2,
)
self.play(
FadeInFrom(terms[1], DOWN),
self.get_student_changes(
"thinking", "pondering", "erm",
look_at_arg=terms,
)
)
self.play(FadeInFromDown(terms[0]))
self.wait()
self.play(Swap(*terms))
self.wait(3)
class FormulaOutOfContext(TeacherStudentsScene):
def construct(self):
formula = TexMobject(
"c_{n} = \\int_0^1 e^{-2\\pi i {n} {t}}f({t}){dt}",
tex_to_color_map={
"{n}": YELLOW,
"{t}": PINK,
}
)
formula.scale(1.5)
formula.next_to(self.students, UP, LARGE_BUFF)
self.add(formula)
self.change_all_student_modes(
"horrified",
look_at_arg=formula,
)
self.play(self.teacher.change, "tease")
self.wait(3)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,371 @@
from manimlib.imports import *
from active_projects.diffyq.part2.heat_equation import BringTwoRodsTogether
from active_projects.diffyq.part3.staging import FourierSeriesIllustraiton
class StepFunctionExample(BringTwoRodsTogether, FourierSeriesIllustraiton):
CONFIG = {
"axes_config": {
"y_min": -1.5,
"y_max": 1.5,
"y_axis_config": {
"unit_size": 2.5,
"tick_frequency": 0.5,
},
"x_min": 0,
"x_max": 1,
"x_axis_config": {
"unit_size": 8,
"tick_frequency": 0.1,
"include_tip": False,
},
},
"y_labels": [-1, 1],
"graph_x_min": 0,
"graph_x_max": 1,
"midpoint": 0.5,
"min_temp": -1,
"max_temp": 1,
"alpha": 0.25,
"step_size": 0.01,
"n_range": range(1, 41, 2),
}
def construct(self):
self.setup_axes()
self.setup_graph()
self.setup_clock()
self.bring_rods_together()
self.let_evolve_for_a_bit()
self.add_labels()
self.compare_to_sine_wave()
self.sum_of_sine_waves()
def bring_rods_together(self):
rods = VGroup(
self.get_rod(0, 0.5),
self.get_rod(0.5, 1),
)
rods.add_updater(self.update_rods)
arrows = VGroup(
Vector(RIGHT).next_to(rods[0], UP),
Vector(LEFT).next_to(rods[1], UP),
)
words = VGroup(
TextMobject("Hot").next_to(rods[0], DOWN),
TextMobject("Cold").next_to(rods[1], DOWN),
)
for pair in rods, words:
pair.save_state()
pair.space_out_submobjects(1.2)
black_rects = VGroup(*[
Square(
side_length=1,
fill_color=BLACK,
fill_opacity=1,
stroke_width=0,
).move_to(self.axes.c2p(0, u))
for u in [1, -1]
])
black_rects[0].add_updater(
lambda m: m.align_to(rods[0].get_right(), LEFT)
)
black_rects[1].add_updater(
lambda m: m.align_to(rods[1].get_left(), RIGHT)
)
self.add(
self.axes,
self.graph,
self.clock,
)
self.add(rods, words)
self.add(black_rects)
kw = {
"run_time": 2,
"rate_func": rush_into,
}
self.play(
Restore(rods, **kw),
Restore(words, **kw),
*map(ShowCreation, arrows)
)
self.remove(black_rects)
self.to_fade = VGroup(words, arrows)
self.rods = rods
def let_evolve_for_a_bit(self):
rods = self.rods
# axes = self.axes
time_label = self.time_label
graph = self.graph
graph.save_state()
graph.add_updater(self.update_graph)
time_label.next_to(self.clock, DOWN)
time_label.add_updater(
lambda d, dt: d.increment_value(dt)
)
rods.add_updater(self.update_rods)
self.add(time_label)
self.play(
FadeOut(self.to_fade),
self.get_clock_anim(1)
)
self.play(self.get_clock_anim(3))
time_label.clear_updaters()
graph.clear_updaters()
self.play(
self.get_clock_anim(
-4,
run_time=1,
rate_func=smooth,
),
graph.restore,
time_label.set_value, 0,
)
rods.clear_updaters()
self.wait()
def add_labels(self):
axes = self.axes
y_axis = axes.y_axis
x_axis = axes.x_axis
y_numbers = y_axis.get_number_mobjects(
*np.arange(-1, 1.5, 0.5),
number_config={
"unit": "^\\circ",
"num_decimal_places": 1,
}
)
x_numbers = x_axis.get_number_mobjects(
*np.arange(0.2, 1.2, 0.2),
number_config={
"num_decimal_places": 1,
},
)
self.play(FadeIn(y_numbers))
self.play(ShowCreationThenFadeAround(y_numbers[-1]))
self.play(ShowCreationThenFadeAround(y_numbers[0]))
self.play(
LaggedStartMap(
FadeInFrom, x_numbers,
lambda m: (m, UP)
),
self.rods.set_opacity, 0.8,
)
self.wait()
def compare_to_sine_wave(self):
phi_tracker = ValueTracker(0)
get_phi = phi_tracker.get_value
k_tracker = ValueTracker(TAU)
get_k = k_tracker.get_value
A_tracker = ValueTracker(1)
get_A = A_tracker.get_value
sine_wave = always_redraw(lambda: self.axes.get_graph(
lambda x: get_A() * np.sin(
get_k() * x - get_phi()
),
x_min=self.graph_x_min,
x_max=self.graph_x_max,
).color_using_background_image("VerticalTempGradient"))
self.play(ShowCreation(sine_wave, run_time=3))
self.wait()
self.play(A_tracker.set_value, 1.25)
self.play(A_tracker.set_value, 0.75)
self.play(phi_tracker.set_value, -PI / 2)
self.play(k_tracker.set_value, 3 * TAU)
self.play(k_tracker.set_value, 2 * TAU)
self.play(
k_tracker.set_value, PI,
A_tracker.set_value, 4 / PI,
run_time=3
)
self.wait()
self.sine_wave = sine_wave
def sum_of_sine_waves(self):
curr_sine_wave = self.sine_wave
axes = self.axes
sine_graphs = self.get_sine_graphs(axes)
partial_sums = self.get_partial_sums(axes, sine_graphs)
curr_partial_sum = partial_sums[0]
curr_partial_sum.set_color(WHITE)
self.play(
FadeOut(curr_sine_wave),
FadeIn(curr_partial_sum),
FadeOut(self.rods),
)
# Copy-pasting from superclass...in theory,
# this should be better abstracted, but eh.
pairs = list(zip(sine_graphs, partial_sums))[1:]
for sine_graph, partial_sum in pairs:
anims1 = [
ShowCreation(sine_graph)
]
partial_sum.set_stroke(BLACK, 4, background=True)
anims2 = [
curr_partial_sum.set_stroke,
{"width": 1, "opacity": 0.25},
curr_partial_sum.set_stroke,
{"width": 0, "background": True},
ReplacementTransform(
sine_graph, partial_sum,
remover=True
),
]
self.play(*anims1)
self.play(*anims2)
curr_partial_sum = partial_sum
#
def setup_axes(self):
super().setup_axes()
self.axes.shift(
self.axes.c2p(0, 0)[1] * DOWN
)
class BreakDownStepFunction(StepFunctionExample):
CONFIG = {
"axes_config": {
"x_axis_config": {
"stroke_width": 2,
},
"y_axis_config": {
"tick_frequency": 0.25,
"stroke_width": 2,
},
"y_min": -1.25,
"y_max": 1.25,
},
"alpha": 0.1,
"wait_time": 30,
}
def construct(self):
self.setup_axes()
self.setup_graph()
self.setup_clock()
self.add_rod()
self.wait()
self.init_updaters()
self.play(
self.get_clock_anim(self.wait_time)
)
def setup_axes(self):
super().setup_axes()
axes = self.axes
axes.to_edge(LEFT)
mini_axes = VGroup(*[
axes.deepcopy()
for x in range(4)
])
for n, ma in zip(it.count(1, 2), mini_axes):
if n == 1:
t1 = TexMobject("1")
t2 = TexMobject("-1")
else:
t1 = TexMobject("1 / " + str(n))
t2 = TexMobject("-1 / " + str(n))
VGroup(t1, t2).scale(1.5)
t1.next_to(ma.y_axis.n2p(1), LEFT, MED_SMALL_BUFF)
t2.next_to(ma.y_axis.n2p(-1), LEFT, MED_SMALL_BUFF)
ma.y_axis.numbers.set_opacity(0)
ma.y_axis.add(t1, t2)
for mob in mini_axes.get_family():
if isinstance(mob, Line):
mob.set_stroke(width=1, family=False)
mini_axes.arrange(DOWN, buff=2)
mini_axes.set_height(FRAME_HEIGHT - 1.5)
mini_axes.to_corner(UR)
self.scale_factor = fdiv(
mini_axes[0].get_width(),
axes.get_width(),
)
# mini_axes.arrange(RIGHT, buff=2)
# mini_axes.set_width(FRAME_WIDTH - 1.5)
# mini_axes.to_edge(LEFT)
dots = TexMobject("\\vdots")
dots.next_to(mini_axes, DOWN)
dots.shift_onto_screen()
self.add(axes)
self.add(mini_axes)
self.add(dots)
self.mini_axes = mini_axes
def setup_graph(self):
super().setup_graph()
graph = self.graph
self.add(graph)
mini_axes = self.mini_axes
mini_graphs = VGroup()
for axes, u, n in zip(mini_axes, it.cycle([1, -1]), it.count(1, 2)):
mini_graph = axes.get_graph(
lambda x: (4 / PI) * (u / 1) * np.cos(PI * n * x),
)
mini_graph.set_stroke(WHITE, width=2)
mini_graphs.add(mini_graph)
# mini_graphs.set_color_by_gradient(
# BLUE, GREEN, RED, YELLOW,
# )
self.mini_graphs = mini_graphs
self.add(mini_graphs)
def setup_clock(self):
super().setup_clock()
clock = self.clock
time_label = self.time_label
clock.move_to(3 * RIGHT)
clock.to_corner(UP)
time_label.next_to(clock, DOWN)
self.add(clock)
self.add(time_label)
def add_rod(self):
self.rod = self.get_rod(0, 1)
self.add(self.rod)
def init_updaters(self):
self.graph.add_updater(self.update_graph)
for mg in self.mini_graphs:
mg.add_updater(
lambda m, dt: self.update_graph(
m, dt,
alpha=self.scale_factor * self.alpha
)
)
self.time_label.add_updater(
lambda d, dt: d.increment_value(dt)
)
self.rod.add_updater(
lambda r: self.update_rods([r])
)

View File

@@ -1,107 +1,6 @@
from manimlib.imports import *
from active_projects.ode.part3.temperature_graphs import TemperatureGraphScene
from active_projects.ode.part2.wordy_scenes import WriteHeatEquationTemplate
class RelationToOtherVideos(Scene):
CONFIG = {
"camera_config": {
"background_color": DARK_GREY,
},
}
def construct(self):
# Show three videos
videos = self.get_video_thumbnails()
brace = Brace(videos, UP)
text = TextMobject("Heat equation")
text.scale(2)
text.next_to(brace, UP)
self.play(
LaggedStartMap(
FadeInFrom, videos,
lambda m: (m, LEFT),
lag_ratio=0.4,
run_time=2,
),
GrowFromCenter(brace),
FadeInFromDown(text),
)
self.wait()
group = Group(text, brace, videos)
# Show Fourier thinking
fourier = ImageMobject("Joseph Fourier")
fourier.set_height(4)
fourier.to_edge(RIGHT)
group.generate_target()
group.target.to_edge(DOWN)
fourier.align_to(group.target[0], DOWN)
bubble = ThoughtBubble(
direction=RIGHT,
width=3,
height=2,
fill_opacity=0.5,
stroke_color=WHITE,
)
bubble[-1].shift(0.25 * DOWN + 0.5 * LEFT)
bubble[:-1].rotate(20 * DEGREES)
for mob in bubble[:-1]:
mob.rotate(-20 * DEGREES)
bubble.move_tip_to(
fourier.get_corner(UL) + DOWN
)
bubble.to_edge(UP, buff=SMALL_BUFF)
self.play(
MoveToTarget(group),
FadeInFrom(fourier, LEFT)
)
self.play(Write(bubble, run_time=1))
self.wait()
# Discount first two
first_two = videos[:2]
first_two.generate_target()
first_two.target.scale(0.5)
first_two.target.to_corner(DL)
new_brace = Brace(first_two.target, UP)
self.play(
# fourier.scale, 0.8,
fourier.match_x, new_brace,
fourier.to_edge, UP,
MoveToTarget(first_two),
Transform(brace, new_brace),
text.scale, 0.7,
text.next_to, new_brace, UP,
FadeOutAndShift(bubble, LEFT),
)
self.play(
videos[2].scale, 1.7,
videos[2].to_corner, UR,
)
self.wait()
#
def get_video_thumbnails(self):
thumbnails = Group(
ImageMobject("diffyq_part2_thumbnail"),
ImageMobject("diffyq_part3_thumbnail"),
ImageMobject("diffyq_part4_thumbnail"),
)
for thumbnail in thumbnails:
thumbnail.set_height(4)
thumbnail.add(SurroundingRectangle(
thumbnail,
color=WHITE,
stroke_width=2,
buff=0
))
thumbnails.arrange(RIGHT, buff=LARGE_BUFF)
thumbnails.set_width(FRAME_WIDTH - 1)
return thumbnails
from active_projects.diffyq.part3.temperature_graphs import TemperatureGraphScene
from active_projects.diffyq.part2.wordy_scenes import WriteHeatEquationTemplate
class ShowLinearity(WriteHeatEquationTemplate, TemperatureGraphScene):
@@ -293,8 +192,8 @@ class ShowLinearity(WriteHeatEquationTemplate, TemperatureGraphScene):
self.play(s2.set_value, -0.5, **kw)
self.play(s1.set_value, -0.2, **kw)
self.play(s2.set_value, 1.5, **kw)
self.play(s1.set_value, 1.2)
self.play(s2.set_value, 0.3)
self.play(s1.set_value, 1.2, **kw)
self.play(s2.set_value, 0.3, **kw)
self.wait()
#
@@ -308,8 +207,8 @@ class ShowLinearity(WriteHeatEquationTemplate, TemperatureGraphScene):
axes_group.to_edge(DOWN, buff=1)
return axes_group
def get_axes(self):
axes = self.get_three_d_axes()
def get_axes(self, **kwargs):
axes = self.get_three_d_axes(**kwargs)
# axes.input_plane.set_fill(opacity=0)
# axes.input_plane.set_stroke(width=0.5)
# axes.add(axes.input_plane)
@@ -341,5 +240,235 @@ class ShowLinearity(WriteHeatEquationTemplate, TemperatureGraphScene):
)
result = always_redraw(get_surface_graph_group)
result.func = func
result.suspend_updating()
return result
class CombineSeveralSolutions(ShowLinearity):
CONFIG = {
"default_surface_config": {
"resolution": (16, 16),
# "resolution": (4, 4),
},
"n_top_graphs": 5,
"axes_config": {
"y_max": 15,
},
"target_scalars": [
0.81, -0.53, 0.41, 0.62, -0.95
],
"final_run_time": 14,
}
def construct(self):
self.init_camera()
self.add_all_axes()
self.setup_all_graphs()
self.show_infinite_family()
self.show_sum()
self.show_time_passing()
def add_all_axes(self):
top_axes_group = VGroup(*[
self.get_axes(
z_min=-1.25,
z_max=1.25,
z_axis_config={
"unit_size": 2,
"tick_frequency": 0.5,
},
)
for x in range(self.n_top_graphs)
])
top_axes_group.arrange(RIGHT, buff=2)
top_axes_group.set_width(FRAME_WIDTH - 1.5)
top_axes_group.to_corner(UL)
dots = TexMobject("\\dots")
dots.next_to(top_axes_group, RIGHT)
low_axes = self.get_axes()
low_axes.center()
low_axes.scale(1.2)
low_axes.to_edge(DOWN, buff=SMALL_BUFF)
self.add(top_axes_group)
self.add(dots)
self.add(low_axes)
self.top_axes_group = top_axes_group
self.low_axes = low_axes
def setup_all_graphs(self):
scalar_trackers = Group(*[
ValueTracker(1)
for x in range(self.n_top_graphs)
])
freqs = np.arange(self.n_top_graphs)
freqs += 1
self.top_graphs = VGroup(*[
self.get_graph(axes, [n], [st])
for axes, n, st in zip(
self.top_axes_group,
freqs,
scalar_trackers,
)
])
self.low_graph = self.get_graph(
self.low_axes, freqs, scalar_trackers
)
self.scalar_trackers = scalar_trackers
def show_infinite_family(self):
top_axes_group = self.top_axes_group
top_graphs = self.top_graphs
scalar_trackers = self.scalar_trackers
decimals = self.get_decimals(
top_axes_group, scalar_trackers
)
self.play(LaggedStart(*[
AnimationGroup(
Write(graph[0]),
FadeIn(graph[1]),
)
for graph in top_graphs
]))
self.wait()
self.play(FadeIn(decimals))
for graph in top_graphs:
graph.resume_updating()
self.play(LaggedStart(*[
ApplyMethod(st.set_value, value)
for st, value in zip(
scalar_trackers,
self.target_scalars,
)
]), run_time=3)
self.wait()
def show_sum(self):
top_graphs = self.top_graphs
low_graph = self.low_graph
low_graph.resume_updating()
low_graph.update()
self.play(
LaggedStart(*[
Transform(
top_graph.copy().set_fill(opacity=0),
low_graph.copy().set_fill(opacity=0),
remover=True,
)
for top_graph in top_graphs
]),
FadeIn(
low_graph,
rate_func=squish_rate_func(smooth, 0.7, 1)
),
run_time=3,
)
self.wait()
def show_time_passing(self):
all_graphs = [*self.top_graphs, self.low_graph]
all_axes = [*self.top_axes_group, self.low_axes]
time_tracker = ValueTracker(0)
get_t = time_tracker.get_value
anims = [
ApplyMethod(
time_tracker.set_value, 1,
run_time=1,
rate_func=linear
)
]
for axes, graph_group in zip(all_axes, all_graphs):
graph_group.clear_updaters()
surface, gslice = graph_group
plane = self.get_const_time_plane(axes)
plane.t_tracker.add_updater(
lambda m: m.set_value(get_t())
)
gslice.axes = axes
gslice.func = graph_group.func
gslice.add_updater(lambda m: m.become(
self.get_time_slice_graph(
m.axes, m.func, t=get_t()
)
))
self.add(gslice)
self.add(plane.t_tracker)
anims.append(FadeIn(plane))
self.play(*anims)
run_time = self.final_run_time
self.play(
time_tracker.increment_value, run_time,
run_time=run_time,
rate_func=linear,
)
#
def get_decimals(self, axes_group, scalar_trackers):
result = VGroup()
for axes, st in zip(axes_group, scalar_trackers):
decimal = DecimalNumber()
decimal.move_to(axes.get_bottom(), UP)
decimal.shift(SMALL_BUFF * RIGHT)
decimal.set_color(YELLOW)
decimal.scalar_tracker = st
times = TexMobject("\\times")
times.next_to(decimal, LEFT, SMALL_BUFF)
decimal.add_updater(lambda d: d.set_value(
d.scalar_tracker.get_value()
))
group = VGroup(times, decimal)
group.scale(0.7)
result.add(group)
return result
class CycleThroughManyLinearCombinations(CombineSeveralSolutions):
CONFIG = {
"default_surface_config": {
"resolution": (16, 16),
# "resolution": (4, 4),
},
"n_cycles": 10,
}
def construct(self):
self.init_camera()
self.add_all_axes()
self.setup_all_graphs()
#
self.cycle_through_superpositions()
def cycle_through_superpositions(self):
top_graphs = self.top_graphs
low_graph = self.low_graph
scalar_trackers = self.scalar_trackers
self.add(self.get_decimals(
self.top_axes_group, scalar_trackers
))
for graph in [low_graph, *top_graphs]:
graph.resume_updating()
self.add(graph)
nst = len(scalar_trackers)
for x in range(self.n_cycles):
self.play(LaggedStart(*[
ApplyMethod(st.set_value, value)
for st, value in zip(
scalar_trackers,
3 * np.random.random(nst) - 1.5
)
]), run_time=3)
self.wait()

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
from manimlib.imports import *
from old_projects.crypto import sha256_tex_mob, bit_string_to_mobject, BitcoinLogo
from from_3b1b.old.crypto import sha256_tex_mob, bit_string_to_mobject, BitcoinLogo
def get_google_logo():
result = SVGMobject(

View File

@@ -2,8 +2,8 @@
from manimlib.imports import *
from old_projects.uncertainty import Flash
from old_projects.WindingNumber import *
from from_3b1b.old.uncertainty import Flash
from from_3b1b.old.WindingNumber import *
# Warning, this file uses ContinualChangingDecimal,

View File

@@ -746,7 +746,7 @@ class StartingCalc101(PiCreatureScene):
def get_aha_image(self):
creature = self.pi_creature.copy()
creature.change_mode("hooray")
from old_projects.eoc.chapter3 import NudgeSideLengthOfCube
from from_3b1b.old.eoc.chapter3 import NudgeSideLengthOfCube
scene = NudgeSideLengthOfCube(
end_at_animation_number=7,
skip_animations=True

View File

@@ -1,7 +1,7 @@
from manimlib.imports import *
from old_projects.lost_lecture import GeometryProofLand
from old_projects.quaternions import SpecialThreeDScene
from old_projects.uncertainty import Flash
from from_3b1b.old.lost_lecture import GeometryProofLand
from from_3b1b.old.quaternions import SpecialThreeDScene
from from_3b1b.old.uncertainty import Flash
class Introduction(TeacherStudentsScene):
@@ -807,7 +807,7 @@ class FunctionGOutputSpace(FunctionGInputSpace):
x_max=2.5,
y_min=-2.5,
y_max=2.5,
number_line_config={'unit_size': 1.5}
axis_config={'unit_size': 1.5}
)
for axis in axes:
numbers = list(range(-2, 3))

View File

@@ -1,5 +1,5 @@
from manimlib.imports import *
from old_projects.brachistochrone.curves import *
from from_3b1b.old.brachistochrone.curves import *
class RollAlongVector(Animation):
CONFIG = {

View File

@@ -3,7 +3,7 @@ import itertools as it
from manimlib.imports import *
from old_projects.brachistochrone.curves import Cycloid
from from_3b1b.old.brachistochrone.curves import Cycloid
class MultilayeredGlass(PhotonScene, ZoomedScene):
CONFIG = {

View File

@@ -3,7 +3,7 @@ import itertools as it
from manimlib.imports import *
from old_projects.brachistochrone.curves import \
from from_3b1b.old.brachistochrone.curves import \
Cycloid, PathSlidingScene, RANDY_SCALE_FACTOR, TryManyPaths

View File

@@ -2,7 +2,7 @@ import numpy as np
import itertools as it
from manimlib.imports import *
from old_projects.brachistochrone.curves import Cycloid
from from_3b1b.old.brachistochrone.curves import Cycloid
class PhysicalIntuition(Scene):
def construct(self):

View File

@@ -2,8 +2,8 @@ import numpy as np
import itertools as it
from manimlib.imports import *
from old_projects.brachistochrone.light import PhotonScene
from old_projects.brachistochrone.curves import *
from from_3b1b.old.brachistochrone.light import PhotonScene
from from_3b1b.old.brachistochrone.curves import *
class MultilayeredScene(Scene):

View File

@@ -3,7 +3,7 @@ import itertools as it
import os
from manimlib.imports import *
from old_projects.brachistochrone.drawing_images import sort_by_color
from from_3b1b.old.brachistochrone.drawing_images import sort_by_color
class Intro(Scene):
def construct(self):

View File

@@ -1,10 +1,10 @@
from old_projects.clacks import question
from old_projects.clacks.solution2 import block_collision_scenes
from old_projects.clacks.solution2 import mirror_scenes
from old_projects.clacks.solution2 import pi_creature_scenes
from old_projects.clacks.solution2 import position_phase_space
from old_projects.clacks.solution2 import simple_scenes
from old_projects.clacks.solution2 import wordy_scenes
from from_3b1b.old.clacks import question
from from_3b1b.old.clacks.solution2 import block_collision_scenes
from from_3b1b.old.clacks.solution2 import mirror_scenes
from from_3b1b.old.clacks.solution2 import pi_creature_scenes
from from_3b1b.old.clacks.solution2 import position_phase_space
from from_3b1b.old.clacks.solution2 import simple_scenes
from from_3b1b.old.clacks.solution2 import wordy_scenes
OUTPUT_DIRECTORY = "clacks/solution2"
SCENES_IN_ORDER = [

View File

@@ -1,6 +1,6 @@
#!/usr/bin/env python
from manimlib.imports import *
from old_projects.clacks.question import BlocksAndWallExample
from from_3b1b.old.clacks.question import BlocksAndWallExample
class NameBump(BlocksAndWallExample):

View File

@@ -325,8 +325,8 @@ class BlocksAndWallScene(Scene):
counter_mob = Integer(self.n_clacks)
counter_mob.next_to(
counter_label[-1], RIGHT,
aligned_edge=DOWN,
)
counter_mob.align_to(counter_label[-1][-1], DOWN)
counter_group = VGroup(
counter_label,
counter_mob,
@@ -747,7 +747,7 @@ class BlocksAndWallExampleMass1e2(BlocksAndWallExample):
"velocity": -0.6,
}
},
"wait_time": 25,
"wait_time": 35,
}
@@ -888,7 +888,7 @@ class PiComputingAlgorithmsAxes(Scene):
y_min=0,
x_max=9,
y_max=5,
number_line_config={
axis_config={
"tick_frequency": 100,
"numbers_with_elongated_ticks": [],
}

View File

@@ -1,6 +1,6 @@
from manimlib.imports import *
from old_projects.clacks.question import *
from old_projects.div_curl import ShowTwoPopulations
from from_3b1b.old.clacks.question import *
from from_3b1b.old.div_curl import ShowTwoPopulations
OUTPUT_DIRECTORY = "clacks/solution1"
@@ -633,7 +633,7 @@ class IntroduceVelocityPhaseSpace(AskAboutFindingNewVelocities):
"x_min": -3.5,
"x_max": 4,
},
"number_line_config": {
"axis_config": {
"unit_size": 0.7,
},
},
@@ -1204,6 +1204,8 @@ class CircleDiagramFromSlidingBlocks(Scene):
"fill_color": GREEN,
"fill_opacity": 0.3,
},
"show_dot": True,
"show_vector": False,
}
def construct(self):
@@ -1211,6 +1213,9 @@ class CircleDiagramFromSlidingBlocks(Scene):
show_flash_animations=False,
write_to_movie=False,
wait_time=0,
file_writer_config={
"output_directory": ".",
}
)
blocks = sliding_blocks_scene.blocks
times = [pair[1] for pair in blocks.clack_data]
@@ -1229,7 +1234,17 @@ class CircleDiagramFromSlidingBlocks(Scene):
dot = Dot(color=RED, radius=0.06)
dot.move_to(lines[0].get_start())
self.add(end_zone, axes, circle, dot)
vector = Vector(lines[0].get_start())
vector.set_color(RED)
vector.add_updater(lambda v: v.put_start_and_end_on(
ORIGIN, dot.get_center()
))
vector.set_stroke(BLACK, 2, background=True)
dot.set_opacity(int(self.show_dot))
vector.set_opacity(int(self.show_vector))
self.add(end_zone, axes, circle, dot, vector)
last_time = 0
for time, line in zip(times, lines):
@@ -1238,7 +1253,7 @@ class CircleDiagramFromSlidingBlocks(Scene):
self.wait(time - last_time)
last_time = time
dot.move_to(line.get_end())
self.add(line, dot)
self.add(line, dot, vector)
self.wait()
def get_circle(self):
@@ -2597,7 +2612,7 @@ class UnitCircleIntuition(Scene):
def draw_unit_circle(self):
unit_size = 2.5
axes = Axes(
number_line_config={"unit_size": unit_size},
axis_config={"unit_size": unit_size},
x_min=-2.5, x_max=2.5,
y_min=-1.5, y_max=1.5,
)

View File

@@ -1,5 +1,5 @@
from manimlib.imports import *
from old_projects.clacks.question import BlocksAndWallExample
from from_3b1b.old.clacks.question import BlocksAndWallExample
class PreviousTwoVideos(BlocksAndWallExample):

View File

@@ -1,7 +1,7 @@
from manimlib.imports import *
from old_projects.clacks.question import Block
from old_projects.clacks.question import Wall
from old_projects.clacks.question import ClackFlashes
from from_3b1b.old.clacks.question import Block
from from_3b1b.old.clacks.question import Wall
from from_3b1b.old.clacks.question import ClackFlashes
class PositionPhaseSpaceScene(Scene):

View File

@@ -1,7 +1,7 @@
from manimlib.imports import *
from old_projects.lost_lecture import ShowWord
from old_projects.clacks.solution2.mirror_scenes import ReflectWorldThroughMirrorNew
from old_projects.clacks.question import Thumbnail
from from_3b1b.old.lost_lecture import ShowWord
from from_3b1b.old.clacks.solution2.mirror_scenes import ReflectWorldThroughMirrorNew
from from_3b1b.old.clacks.question import Thumbnail
class WrapperScene(Scene):

View File

@@ -1,5 +1,5 @@
from manimlib.imports import *
from old_projects.clacks.solution2.position_phase_space import ShowMomentumConservation
from from_3b1b.old.clacks.solution2.position_phase_space import ShowMomentumConservation
class ConnectionToOptics(Scene):

View File

@@ -1,7 +1,7 @@
from manimlib.imports import *
from old_projects.lost_lecture import Orbiting
from old_projects.lost_lecture import ShowWord
from from_3b1b.old.lost_lecture import Orbiting
from from_3b1b.old.lost_lecture import ShowWord
class LogoGeneration(LogoGenerationTemplate):

View File

@@ -2925,7 +2925,7 @@ class PhaseSpaceOfPopulationModel(ShowTwoPopulations, PiCreatureScene, MovingCam
y_min=0,
y_max=55,
y_axis_config={"unit_size": 0.09},
number_line_config={
axis_config={
"tick_frequency": 10,
},
)
@@ -4217,7 +4217,7 @@ class BroughtToYouBy(PiCreatureScene):
spiral = Line(0.5 * RIGHT, 0.5 * RIGHT + 70 * UP)
spiral.insert_n_curves(1000)
from old_projects.zeta import zeta
from from_3b1b.old.zeta import zeta
spiral.apply_complex_function(zeta)
step = 0.1
spiral = VGroup(*[

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