Show code cell content
import mmf_setup;mmf_setup.nbinit()
import logging;logging.getLogger('matplotlib').setLevel(logging.CRITICAL)
%matplotlib inline
import numpy as np, matplotlib.pyplot as plt
This cell adds /home/docs/checkouts/readthedocs.org/user_builds/physics-581-the-standard-model/checkouts/latest/src to your path, and contains some definitions for equations and some CSS for styling the notebook. If things look a bit strange, please try the following:
- Choose "Trust Notebook" from the "File" menu.
- Re-execute this cell.
- Reload the notebook.
JupyterBook Demonstration#
This document demonstrates some of the features provided by the documentation. It can serve as a starting point for your own documentation.
This documentation is formatted using an extension to Markdown called MyST which allows full interoperability with Sphinx, the system used to build the documentation. Here we demonstrate some features. For more details, please see:
Math#
You can use LaTeX math with [MathJaX][].
Example#
Here we implement a simple example of a pendulum of mass \(m\) hanging down distance \(r\) from a pivot point in a gravitational field \(g>0\) with coordinate \(\theta\) so that the mass is at \((x, z) = (r\sin\theta, -r\cos\theta)\) and \(\theta=0\) is the downward equilibrium position:
Note
On [CoCalc][], only a subset of the math will render in the live Markdown editor. This
uses KaTeX, which is much faster than [MathJaX][], but more limited. The final
documentation will use [MathJaX][], and loads the macros defined in
Docs/_static/math_defs.tex.
SI Units#
In LaTeX, I like to use the siunitx package. This is not currently supported in
MathJax (they could not get funding),
but can be mocked up with some defines.
The idea is that we use the macros for HTML, but substitute the appropriate
\usepackage{siunitx} in the LaTeX files. (This second step is currently not implemented)
Jupyter Notebooks#
This document is actually a Jupyter notebook, synchronized with Jupytext. The top of the document contains information about the kernel that should be used etc. These are parsed using MyST-NB and the output of cells will be displayed. For example, here is a plot demonstrating Liouville’s Theorem.
Show code cell source
plt.rcParams['figure.dpi'] = 300
from scipy.integrate import solve_ivp
alpha = 0.0
m = r = g = 1.0
w = g/r
T = 2*np.pi / w # Period of small oscillations.
def f(t, y):
# We will simultaneously evolve N points.
N = len(y)//2
theta, p_theta = np.reshape(y, (2, N))
dy = np.array([p_theta/m/r**2*np.exp(-alpha*t),
-m*g*r*np.sin(theta)*np.exp(alpha*t)])
return dy.ravel()
# Start with a circle of points in phase space centered here
def plot_set(y, dy=0.1, T=T, phase_space=True, N=10, Nt=5, c='C0',
Ncirc=1000, max_step=0.01, _alpha=0.7,
fig=None, ax=None):
"""Plot the phase flow of a circle centered about y0.
Arguments
---------
y : (theta0, ptheta_0)
Center of initial circle.
dy : float
Radius of initial circle.
T : float
Time to evolve to.
phase_space : bool
If `True`, plot in phase space $(q, p)$, otherwise plot in
the "physical" phase space $(q, P)$ where $P = pe^{-\alpha t}$.
N : int
Number of points to show on circle and along path.
Nt : int
Number of images along trajectory to show.
c : color
Color.
alpha : float
Transparency of regions.
max_step : float
Maximum spacing for times dt.
Ncirc : int
Minimum number of points in circle.
"""
global alpha
skip = int(np.ceil(Ncirc // N))
N_ = N * skip
th = np.linspace(0, 2*np.pi, N_ + 1)[:-1]
z = dy * np.exp(1j*th) + np.asarray(y).view(dtype=complex)
y0 = np.ravel([z.real, z.imag])
skip_t = int(np.ceil(T / max_step / Nt))
Nt_ = Nt * skip_t + 1
t_eval = np.linspace(0, T, Nt_)
res = solve_ivp(f, t_span=(0, T), y0=y0, t_eval=t_eval)
assert Nt_ == len(res.t)
thetas, p_thetas = res.y.reshape(2, N_, Nt_)
ylabel = r"$p_{\theta}$"
if phase_space:
ylabel = r"$P_{\theta}=p_{\theta}e^{-\alpha t}$"
p_thetas *= np.exp(-alpha * res.t)
if ax is None:
fig, ax = plt.subplots()
ax.plot(thetas[::skip].T, p_thetas[::skip].T, "-k", lw=0.1)
for n in range(Nt+1):
tind = n*skip_t
ax.plot(thetas[::skip, tind], p_thetas[::skip, tind], '.', ms=0.5, c=c)
ax.fill(thetas[:, tind], p_thetas[:, tind], c=c, alpha=_alpha)
ax.set(xlabel=r"$\theta$", ylabel=ylabel, aspect=1)
return fig, ax
fig, ax = plt.subplots(figsize=(10,5))
for n, y in enumerate(np.linspace(0.25, 1.75, 6)):
plot_set(y=(y, y), c=f"C{n}", ax=ax)
Details
We start a code-block with:
```{code-cell}
:tags: [hide-input, full-width]
...
```
This indicates that it is a code cell, to be run with python 3, and has some tags to make the cell and output full width, but hiding the code. (There is a link to click to show the code.)
If you need more control, you can glue the output to a variable, then load it as a proper figure, insert it in a table, etc.
Manim#
We provide experimental support for Manim Community – the community edition of the animation software used by the 3Blue1Brown project. Here we demonstrate an animation of the Jacobi elliptic functions.
Show code cell content
import manim.utils.ipython_magic
Show code cell source
%%manim -v WARNING --progress_bar None -qm JacobiEllipse
from scipy.special import ellipj, ellipkinc
from manim import *
config.media_width = "100%"
config.media_embed = True
my_tex_template = TexTemplate()
with open("_static/math_defs.tex") as f:
my_tex_template.add_to_preamble(f.read())
def get_scd(phi, k):
m = k**2
u = ellipkinc(phi, m)
s, c, d, phi_ = ellipj(u, m)
return s, c, d
def get_xyr(phi, k):
s, c, d = get_scd(phi, k)
r = 1/d
x, y = r*c, r*s
return x, y, r
class JacobiEllipse(Scene):
def construct(self):
config["tex_template"] = my_tex_template
config["media_width"] = "100%"
class colors:
ellipse = YELLOW
x = BLUE
y = GREEN
r = RED
phi = ValueTracker(0.01)
k = 0.8
axes = Axes(x_range=[0, 2*np.pi, 1],
y_range=[-2, 2, 1],
x_length=6,
y_length=4,
axis_config=dict(include_tip=False),
x_axis_config=dict(numbers_to_exclude=[0]),
).add_coordinates()
plane = PolarPlane(radius_max=2).add_coordinates()
x = lambda phi: get_xyr(phi, k)[0]
y = lambda phi: get_xyr(phi, k)[1]
r = lambda phi: get_xyr(phi, k)[2]
g_ellipse = plane.plot_polar_graph(r, [0, 2*np.pi], color=colors.ellipse)
points_colors = [(x, colors.x), (y, colors.y), (r, colors.r)]
x_graph, y_graph, r_graph = [axes.plot(_x, color=_c) for _x, _c in points_colors]
graphs = VGroup(x_graph, y_graph, r_graph)
dot = always_redraw(lambda:
Dot(plane.polar_to_point(r(phi.get_value()), phi.get_value()),
fill_color=colors.ellipse,
fill_opacity=0.8))
@always_redraw
def lines():
c2p = plane.coords_to_point
phi_ = phi.get_value()
x_, y_ = x(phi_), y(phi_)
return VGroup(
Line(c2p(0, 0), c2p(x_, 0), color=colors.x),
Line(c2p(0, y_), c2p(x_, y_), color=colors.x),
Line(c2p(0, 0), c2p(0, y_), color=colors.y),
Line(c2p(x_, 0), c2p(x_, y_), color=colors.y),
Line(axes.c2p(phi_, y_), c2p(x_, y_), color=colors.y),
Line(c2p(0, 0), c2p(x_, y_), color=colors.r),
).set_opacity(0.8)
dots = always_redraw(lambda:
VGroup(*(Dot(axes.c2p(phi.get_value(), _x(phi.get_value())), fill_color=_c, fill_opacity=1)
for _x, _c in points_colors)))
a_group = VGroup(axes, dots, graphs)
p_group = VGroup(plane, g_ellipse, dot, lines)
a_group.shift(RIGHT*2)
p_group.shift(LEFT*4)
labels = VGroup(
axes.get_graph_label(
x_graph, label=r"x=\cn(u, k)", color=colors.x,
x_val=2.5, direction=DOWN).shift(0.2*LEFT),
axes.get_graph_label(
y_graph, label=r"y=\sn(u, k)", color=colors.y,
x_val=4.5, direction=DR),
axes.get_graph_label(
r_graph, label=r"r=1/\dn(u, k)", color=colors.r,
x_val=2, direction=UR),
)
#labels.next_to(a_group, RIGHT)
self.add(p_group, a_group, labels)
self.play(phi.animate.set_value(2*np.pi), run_time=5, rate_func=linear)
Manim Community v0.18.1
[10/27/24 03:00:02] ERROR LaTeX compilation error: LaTeX Error: Command \span already tex_file_writing.py:314 defined.
[E 03:00:02 manim] LaTeX compilation error: LaTeX Error: Command \span already defined.
tex_file_writing.py:314
ERROR Context of error: tex_file_writing.py:348 \DeclareMathOperator{\sgn}{sgn} \DeclareMathOperator{\order}{O} -> \DeclareMathOperator{\diag}{diag} \DeclareMathOperator{\span}{span} \newcommand{\mylabel}[1]{\label{#1}\tag{#1}} \newcommand{\degree}{\circ}
[E 03:00:02 manim] Context of error:
\DeclareMathOperator{\sgn}{sgn}
\DeclareMathOperator{\order}{O}
-> \DeclareMathOperator{\diag}{diag}
\DeclareMathOperator{\span}{span}
\newcommand{\mylabel}[1]{\label{#1}\tag{#1}}
\newcommand{\degree}{\circ}
tex_file_writing.py:348
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
Cell In[4], line 1
----> 1 get_ipython().run_cell_magic('manim', '-v WARNING --progress_bar None -qm JacobiEllipse', 'from scipy.special import ellipj, ellipkinc\nfrom manim import *\n\nconfig.media_width = "100%"\nconfig.media_embed = True\n\nmy_tex_template = TexTemplate()\nwith open("_static/math_defs.tex") as f:\n my_tex_template.add_to_preamble(f.read())\n\ndef get_scd(phi, k):\n m = k**2\n u = ellipkinc(phi, m)\n s, c, d, phi_ = ellipj(u, m)\n return s, c, d\n\ndef get_xyr(phi, k):\n s, c, d = get_scd(phi, k)\n r = 1/d\n x, y = r*c, r*s\n return x, y, r\n\nclass JacobiEllipse(Scene):\n def construct(self):\n config["tex_template"] = my_tex_template\n config["media_width"] = "100%"\n class colors:\n ellipse = YELLOW\n x = BLUE\n y = GREEN\n r = RED\n \n phi = ValueTracker(0.01)\n k = 0.8\n axes = Axes(x_range=[0, 2*np.pi, 1], \n y_range=[-2, 2, 1],\n x_length=6, \n y_length=4,\n axis_config=dict(include_tip=False),\n x_axis_config=dict(numbers_to_exclude=[0]),\n ).add_coordinates()\n \n \n plane = PolarPlane(radius_max=2).add_coordinates()\n\n x = lambda phi: get_xyr(phi, k)[0]\n y = lambda phi: get_xyr(phi, k)[1]\n r = lambda phi: get_xyr(phi, k)[2]\n \n g_ellipse = plane.plot_polar_graph(r, [0, 2*np.pi], color=colors.ellipse)\n \n points_colors = [(x, colors.x), (y, colors.y), (r, colors.r)]\n x_graph, y_graph, r_graph = [axes.plot(_x, color=_c) for _x, _c in points_colors]\n graphs = VGroup(x_graph, y_graph, r_graph)\n \n dot = always_redraw(lambda:\n Dot(plane.polar_to_point(r(phi.get_value()), phi.get_value()), \n fill_color=colors.ellipse, \n fill_opacity=0.8))\n\n @always_redraw\n def lines():\n c2p = plane.coords_to_point\n phi_ = phi.get_value()\n x_, y_ = x(phi_), y(phi_)\n return VGroup(\n Line(c2p(0, 0), c2p(x_, 0), color=colors.x),\n Line(c2p(0, y_), c2p(x_, y_), color=colors.x),\n Line(c2p(0, 0), c2p(0, y_), color=colors.y),\n Line(c2p(x_, 0), c2p(x_, y_), color=colors.y),\n Line(axes.c2p(phi_, y_), c2p(x_, y_), color=colors.y),\n Line(c2p(0, 0), c2p(x_, y_), color=colors.r),\n ).set_opacity(0.8)\n\n dots = always_redraw(lambda:\n VGroup(*(Dot(axes.c2p(phi.get_value(), _x(phi.get_value())), fill_color=_c, fill_opacity=1)\n for _x, _c in points_colors)))\n\n a_group = VGroup(axes, dots, graphs)\n p_group = VGroup(plane, g_ellipse, dot, lines)\n a_group.shift(RIGHT*2)\n p_group.shift(LEFT*4)\n \n labels = VGroup(\n axes.get_graph_label(\n x_graph, label=r"x=\\cn(u, k)", color=colors.x,\n x_val=2.5, direction=DOWN).shift(0.2*LEFT),\n axes.get_graph_label(\n y_graph, label=r"y=\\sn(u, k)", color=colors.y,\n x_val=4.5, direction=DR),\n axes.get_graph_label(\n r_graph, label=r"r=1/\\dn(u, k)", color=colors.r,\n x_val=2, direction=UR),\n )\n #labels.next_to(a_group, RIGHT)\n self.add(p_group, a_group, labels)\n self.play(phi.animate.set_value(2*np.pi), run_time=5, rate_func=linear)\n')
File ~/checkouts/readthedocs.org/user_builds/physics-581-the-standard-model/conda/latest/lib/python3.11/site-packages/IPython/core/interactiveshell.py:2541, in InteractiveShell.run_cell_magic(self, magic_name, line, cell)
2539 with self.builtin_trap:
2540 args = (magic_arg_s, cell)
-> 2541 result = fn(*args, **kwargs)
2543 # The code below prevents the output from being displayed
2544 # when using magics with decorator @output_can_be_silenced
2545 # when the last Python token in the expression is a ';'.
2546 if getattr(fn, magic.MAGIC_OUTPUT_CAN_BE_SILENCED, False):
File ~/checkouts/readthedocs.org/user_builds/physics-581-the-standard-model/conda/latest/lib/python3.11/site-packages/manim/utils/ipython_magic.py:143, in ManimMagic.manim(self, line, cell, local_ns)
141 SceneClass = local_ns[config["scene_names"][0]]
142 scene = SceneClass(renderer=renderer)
--> 143 scene.render()
144 finally:
145 # Shader cache becomes invalid as the context is destroyed
146 shader_program_cache.clear()
File ~/checkouts/readthedocs.org/user_builds/physics-581-the-standard-model/conda/latest/lib/python3.11/site-packages/manim/scene/scene.py:229, in Scene.render(self, preview)
227 self.setup()
228 try:
--> 229 self.construct()
230 except EndSceneEarlyException:
231 pass
File <string>:41, in construct(self)
File ~/checkouts/readthedocs.org/user_builds/physics-581-the-standard-model/conda/latest/lib/python3.11/site-packages/manim/mobject/graphing/coordinate_systems.py:428, in CoordinateSystem.add_coordinates(self, *axes_numbers, **kwargs)
426 labels = axis.labels
427 else:
--> 428 axis.add_numbers(values, **kwargs)
429 labels = axis.numbers
430 self.coordinate_labels.add(labels)
File ~/checkouts/readthedocs.org/user_builds/physics-581-the-standard-model/conda/latest/lib/python3.11/site-packages/manim/mobject/graphing/number_line.py:533, in NumberLine.add_numbers(self, x_values, excluding, font_size, label_constructor, **kwargs)
530 if x in excluding:
531 continue
532 numbers.add(
--> 533 self.get_number_mobject(
534 x,
535 font_size=font_size,
536 label_constructor=label_constructor,
537 **kwargs,
538 )
539 )
540 self.add(numbers)
541 self.numbers = numbers
File ~/checkouts/readthedocs.org/user_builds/physics-581-the-standard-model/conda/latest/lib/python3.11/site-packages/manim/mobject/graphing/number_line.py:471, in NumberLine.get_number_mobject(self, x, direction, buff, font_size, label_constructor, **number_config)
468 if label_constructor is None:
469 label_constructor = self.label_constructor
--> 471 num_mob = DecimalNumber(
472 x, font_size=font_size, mob_class=label_constructor, **number_config
473 )
475 num_mob.next_to(self.number_to_point(x), direction=direction, buff=buff)
476 if x < 0 and self.label_direction[0] == 0:
477 # Align without the minus sign
File ~/checkouts/readthedocs.org/user_builds/physics-581-the-standard-model/conda/latest/lib/python3.11/site-packages/manim/mobject/text/numbers.py:135, in DecimalNumber.__init__(self, number, num_decimal_places, mob_class, include_sign, group_with_commas, digit_buff_per_font_unit, show_ellipsis, unit, unit_buff_per_font_unit, include_background_rectangle, edge_to_fix, font_size, stroke_width, fill_opacity, **kwargs)
117 self.initial_config = kwargs.copy()
118 self.initial_config.update(
119 {
120 "num_decimal_places": num_decimal_places,
(...)
132 },
133 )
--> 135 self._set_submobjects_from_number(number)
136 self.init_colors()
File ~/checkouts/readthedocs.org/user_builds/physics-581-the-standard-model/conda/latest/lib/python3.11/site-packages/manim/mobject/text/numbers.py:160, in DecimalNumber._set_submobjects_from_number(self, number)
157 self.submobjects = []
159 num_string = self._get_num_string(number)
--> 160 self.add(*(map(self._string_to_mob, num_string)))
162 # Add non-numerical bits
163 if self.show_ellipsis:
File ~/checkouts/readthedocs.org/user_builds/physics-581-the-standard-model/conda/latest/lib/python3.11/site-packages/manim/mobject/text/numbers.py:225, in DecimalNumber._string_to_mob(self, string, mob_class, **kwargs)
222 mob_class = self.mob_class
224 if string not in string_to_mob_map:
--> 225 string_to_mob_map[string] = mob_class(string, **kwargs)
226 mob = string_to_mob_map[string].copy()
227 mob.font_size = self._font_size
File ~/checkouts/readthedocs.org/user_builds/physics-581-the-standard-model/conda/latest/lib/python3.11/site-packages/manim/mobject/text/tex_mobject.py:293, in MathTex.__init__(self, arg_separator, substrings_to_isolate, tex_to_color_map, tex_environment, *tex_strings, **kwargs)
280 if self.brace_notation_split_occurred:
281 logger.error(
282 dedent(
283 """\
(...)
291 ),
292 )
--> 293 raise compilation_error
294 self.set_color_by_tex_to_color_map(self.tex_to_color_map)
296 if self.organize_left_to_right:
File ~/checkouts/readthedocs.org/user_builds/physics-581-the-standard-model/conda/latest/lib/python3.11/site-packages/manim/mobject/text/tex_mobject.py:272, in MathTex.__init__(self, arg_separator, substrings_to_isolate, tex_to_color_map, tex_environment, *tex_strings, **kwargs)
270 self.tex_strings = self._break_up_tex_strings(tex_strings)
271 try:
--> 272 super().__init__(
273 self.arg_separator.join(self.tex_strings),
274 tex_environment=self.tex_environment,
275 tex_template=self.tex_template,
276 **kwargs,
277 )
278 self._break_up_by_substrings()
279 except ValueError as compilation_error:
File ~/checkouts/readthedocs.org/user_builds/physics-581-the-standard-model/conda/latest/lib/python3.11/site-packages/manim/mobject/text/tex_mobject.py:81, in SingleStringMathTex.__init__(self, tex_string, stroke_width, should_center, height, organize_left_to_right, tex_environment, tex_template, font_size, **kwargs)
79 assert isinstance(tex_string, str)
80 self.tex_string = tex_string
---> 81 file_name = tex_to_svg_file(
82 self._get_modified_expression(tex_string),
83 environment=self.tex_environment,
84 tex_template=self.tex_template,
85 )
86 super().__init__(
87 file_name=file_name,
88 should_center=should_center,
(...)
95 **kwargs,
96 )
97 self.init_colors()
File ~/checkouts/readthedocs.org/user_builds/physics-581-the-standard-model/conda/latest/lib/python3.11/site-packages/manim/utils/tex_file_writing.py:63, in tex_to_svg_file(expression, environment, tex_template)
60 if svg_file.exists():
61 return svg_file
---> 63 dvi_file = compile_tex(
64 tex_file,
65 tex_template.tex_compiler,
66 tex_template.output_format,
67 )
68 svg_file = convert_to_svg(dvi_file, tex_template.output_format)
69 if not config["no_latex_cleanup"]:
File ~/checkouts/readthedocs.org/user_builds/physics-581-the-standard-model/conda/latest/lib/python3.11/site-packages/manim/utils/tex_file_writing.py:213, in compile_tex(tex_file, tex_compiler, output_format)
211 log_file = tex_file.with_suffix(".log")
212 print_all_tex_errors(log_file, tex_compiler, tex_file)
--> 213 raise ValueError(
214 f"{tex_compiler} error converting to"
215 f" {output_format[1:]}. See log output above or"
216 f" the log file: {log_file}",
217 )
218 return result
ValueError: latex error converting to dvi. See log output above or the log file: media/Tex/6056ff848b3908bc.log
Warning
We need a Manim >= 0.15.0 to get this to work, resolving issue 2441 by embeding the video in the output.