indicatrix_old.py
¶
Old way of visualizing indicatrix & figuratrix.
- Requires Python packages/modules:
- class gme.plot.indicatrix_old.IndicatrixOld(dpi: int = 100, font_size: int = 11)¶
Old way of visualizing indicatrix & figuratrix.
Extends
gme.plot.base.Graphing
.- annotations(axes: matplotlib.axes._axes.Axes, beta_: float, tanalpha_: float) → None¶
Do some more annotations.
- comparison_logpolar(gmeq: sympy.core.relational.Equality, name: str, fig_size: Optional[Tuple[float, float]] = None, dpi: Optional[float] = None, varphi_: float = 1, n_points: int = 100, idtx_pz_min: float = 0.001, idtx_pz_max: float = 1000, fgtx_pz_min: float = 0.001, fgtx_pz_max: float = 1000, y_limits: Optional[Tuple[float, float]] = None) → None¶
Plot both indicatrix and figuratrix on one log-polar graph.
- figuratrix(gmeq: sympy.core.relational.Equality, varphi_: float, n_points: int, pz_min_: float = 1e-05, pz_max_: float = 50) → Tuple[numpy.ndarray, numpy.ndarray, sympy.core.relational.Equality]¶
Generate figuratrix.
- indicatrix(gmeq: sympy.core.relational.Equality, varphi_: float, n_points: int, pz_min_: float = 1e-05, pz_max_: float = 300) → Tuple[numpy.ndarray, numpy.ndarray, sympy.core.relational.Equality, sympy.core.relational.Equality]¶
Generate figuratrix.
- legend(gmeq: sympy.core.relational.Equality, axes: matplotlib.axes._axes.Axes, do_legend: bool, do_half: bool, do_ray_slowness: bool = False) → None¶
Construct and place a legend.
- lines_and_points(pd: Dict, axes: matplotlib.axes._axes.Axes, zoomx: numpy.ndarray, do_pz: bool, do_shapes: bool) → None¶
Plot some lines and points.
- plot_figuratrix(fgtx_px_array: numpy.ndarray, fgtx_pz_array: numpy.ndarray, maybe_recip_fn: Callable, do_ray_slowness: bool = False) → None¶
Plot figuratrix.
- plot_indicatrix(idtx_rdotx_array: numpy.ndarray, idtx_rdotz_array: numpy.ndarray, maybe_recip_fn: Callable, do_ray_slowness: bool = False) → None¶
Plot indicatrix.
- plot_unit_circle(varphi_: float, do_varphi_circle: bool) → None¶
Plot unit circle as a reference for indicatrix/figuratrix.
- relative_geometry(gmeq: sympy.core.relational.Equality, name: str, fig_size: Optional[Tuple[float, float]] = None, dpi: Optional[float] = None, varphi_: float = 1, zoom_factor: float = 1, do_half: bool = False, do_legend: bool = True, do_text_labels: bool = True, do_arrows: bool = True, do_lines_points: bool = True, do_shapes: bool = False, do_varphi_circle: bool = False, do_pz: bool = False, do_ray_slowness: bool = False, x_max: float = 3.4, n_points: int = 100, pz_min_: float = 0.1) → None¶
Plot indicatrix relative geometry.
Plot the loci of \(\mathbf{\widetilde{p}}\) and \(\mathbf{r}\) and their behavior defined by \(F\) relative to the \(\xi\) circle.
- Parameters
gmeq – GME model equations class instance defined in
gme.core.equations
varphi_choice – the value of \(\varphi\) to use
zoom_factor – fractional zoom factor relative to preassigned graph limits
do_half – plot only for \(x\geq0\)?
do_annotations – plot annotated arcs, faster/slower arrows?
do_legend – display the legend?
do_text_labels – display text annotations?
do_arrows – display vector/covector arrows?
do_lines_points – display dashed/dotted tangent lines etc?
do_shapes – plot key points using polygon symbols rather than simple circles
do_varphi_circle – plot the \(\xi\) (typically unit) circle?
do_pz – plot horizontal dotted line indicating magnitude of \(p_z\)
do_ray_slowness – invert ray speed (but keep ray direction) in indicatrix?
Code¶
"""
Old way of visualizing indicatrix & figuratrix.
---------------------------------------------------------------------
Requires Python packages/modules:
- :mod:`NumPy <numpy>`
- :mod:`SymPy <sympy>`
- :mod:`MatPlotLib <matplotlib>`
- `GME`_
.. _GMPLib: https://github.com/geomorphysics/GMPLib
.. _GME: https://github.com/geomorphysics/GME
.. _Matrix:
https://docs.sympy.org/latest/modules/matrices/immutablematrices.html
---------------------------------------------------------------------
"""
# Library
import warnings
from typing import Tuple, Callable, Dict
# NumPy
import numpy as np
# SymPy
from sympy import Eq, N, re, factor, lambdify
# MatPlotLib
import matplotlib.pyplot as plt
from matplotlib.pyplot import Axes
import matplotlib.patches as mpatches
from matplotlib.patches import Circle, RegularPolygon
# GME
from gme.core.symbols import px, pz, varphi, pz_min
from gme.plot.base import Graphing
warnings.filterwarnings("ignore")
__all__ = ["IndicatrixOld"]
class IndicatrixOld(Graphing):
"""
Old way of visualizing indicatrix & figuratrix.
Extends :class:`gme.plot.base.Graphing`.
"""
def comparison_logpolar(
self,
gmeq: Eq,
name: str,
fig_size: Tuple[float, float] = None,
dpi: float = None,
varphi_: float = 1,
n_points: int = 100,
idtx_pz_min: float = 1e-3,
idtx_pz_max: float = 1000,
fgtx_pz_min: float = 1e-3,
fgtx_pz_max: float = 1000,
y_limits: Tuple[float, float] = None,
) -> None:
"""Plot both indicatrix and figuratrix on one log-polar graph."""
_ = self.create_figure(name, fig_size=fig_size, dpi=dpi)
plt.title("Erosion indicatrix & figuratrix", va="bottom", pad=15)
plt.grid(False, ls=":")
# px_pz_lambda \
# = lambdify( [pz],
# gmeq.fgtx_px_pz_varphi_eqn.rhs.subs({varphi:varphi_}) )
# fgtx_pz_array \
# = -np.power(10,np.linspace(np.log10(1000),np.log10(1e-6),n_points))
# fgtx_px_array
# = np.array([float(re(N(px_pz_lambda(pz_)))) for pz_ in fgtx_pz_array])
# Compute figuratrix
fgtx_px_array, fgtx_pz_array, _ = self.figuratrix(
gmeq, varphi_, n_points, fgtx_pz_min, fgtx_pz_max
)
fgtx_p_array = np.log10(
np.sqrt(fgtx_px_array ** 2 + fgtx_pz_array ** 2)
)
fgtx_tanbeta_array = -fgtx_px_array / fgtx_pz_array
fgtx_beta_array = np.arctan(fgtx_tanbeta_array)
fgtx_theta_array = np.concatenate(
[fgtx_beta_array, (2 * np.pi - fgtx_beta_array)[::-1]]
)
fgtx_p_array = np.concatenate([fgtx_p_array, fgtx_p_array[::-1]])
# Compute indicatrix
idtx_rdotx_array, idtx_rdotz_array, _, _ = self.indicatrix(
gmeq, varphi_, n_points, idtx_pz_min, idtx_pz_max
)
idtx_rdot_array = np.log10(
np.sqrt(idtx_rdotx_array ** 2 + idtx_rdotz_array ** 2)
)
idtx_alpha_array = np.arctan(-idtx_rdotx_array / idtx_rdotz_array)
idtx_theta_negrdot_array = idtx_alpha_array[idtx_rdotz_array < 0]
idtx_rdot_negrdot_array = idtx_rdot_array[idtx_rdotz_array < 0]
idtx_theta_posrdot_array = (
np.pi + idtx_alpha_array[idtx_rdotz_array > 0]
)
idtx_rdot_posrdot_array = idtx_rdot_array[idtx_rdotz_array > 0]
idtx_theta_array = np.concatenate(
[idtx_theta_negrdot_array, idtx_theta_posrdot_array]
)
idtx_rdot_array = np.concatenate(
[idtx_rdot_negrdot_array, idtx_rdot_posrdot_array]
)
# Compute reference unit circle
unit_circle_beta_array = np.linspace(0, 2 * np.pi)
# Do the basic plotting
# idtx_label = r'indicatrix $F(\mathbf{v},\alpha)$'
# fgtx_label = r'figuratrix $F^*(\mathbf{\widetilde{p}},\beta)$'
idtx_label = r"ray velocity"
fgtx_label = r"normal slowness"
plt.polar(
fgtx_theta_array,
fgtx_p_array,
"DarkBlue",
"-",
lw=1.5,
label=fgtx_label,
)
plt.polar(
idtx_theta_array,
idtx_rdot_array,
"DarkRed",
ls="-",
lw=1.5,
label=idtx_label,
)
plt.polar(
2 * np.pi - idtx_theta_array,
idtx_rdot_array,
"DarkRed",
ls="-",
lw=1.5,
)
# plt.polar( idtx_theta_posrdot_array, idtx_rdot_posrdot_array,
# 'magenta', ls='-', lw=3)
# plt.polar( idtx_theta_negrdot_array, idtx_rdot_negrdot_array,
# 'k', ls='-', lw=3)
plt.polar(
unit_circle_beta_array,
unit_circle_beta_array * 0,
"g",
":",
lw=1,
label="unit circle",
)
# Critical angles
beta_crit = np.arctan(float(gmeq.tanbeta_crit))
alpha_crit = np.pi / 2 + np.arctan(float(gmeq.tanalpha_crit))
plt.polar(
[beta_crit, beta_crit],
[-2, 3],
":",
color="DarkBlue",
label=r"$\beta=\beta_c$",
)
plt.polar(
[alpha_crit, alpha_crit],
[-2, 3],
":",
color="DarkRed",
label=r"$\alpha=\alpha_{\mathrm{ext}}$",
)
# Labelling etc
posn_list = (0, 0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75)
xtick_posns = [(-np.pi / i_ if i_ != 0 else np.pi) for i_ in posn_list]
xtick_posns = plt.xticks()[0]
xtick_labels = [
(
r"$\frac{\pi}{" + f"{int(x_)}" + "}$"
if x_ > 0
else r"$-\frac{\pi}{" + f"{int(-x_)}" + "}$"
if x_ != 0
else r"$0$"
)
for x_ in posn_list
]
xtick_labels = [
r"$\beta=0$",
r"$\beta=\frac{\pi}{4}$",
r"$\qquad\alpha=0,\beta=\frac{\pi}{2}$",
r"$\alpha=\frac{\pi}{4}$",
r"$\alpha=\pm\frac{\pi}{2}$",
r"$\alpha=-\frac{\pi}{4}$",
r"$\alpha=0,\beta=-\frac{\pi}{2}\quad$",
r"$\beta=-\frac{\pi}{4}$",
]
plt.xticks(xtick_posns, xtick_labels)
y_limits_: Tuple[float, float]
if y_limits is None:
y_limits_ = (-2, 3)
ytick_posns = [-1, 0, 1, 2, 3, 4]
else:
y_limits_ = y_limits
ytick_posns = list(range(int(y_limits_[0]), int(y_limits_[1]) + 2))
plt.ylim(*y_limits_)
ytick_labels = [rf"$10^{int(y_)}$" for y_ in ytick_posns]
plt.yticks(ytick_posns, ytick_labels)
axes = plt.gca()
plt.text(
np.pi / 1.1,
(1 + y_limits_[1] - y_limits_[0]) * 2 / 3 + y_limits_[0],
rf"$\eta={gmeq.eta_}$",
fontsize=16,
)
axes.set_theta_zero_location("S")
handles, labels = axes.get_legend_handles_labels()
subset = (3, 2, 0, 5, 6)
handles = [handles[idx] for idx in subset]
labels = [labels[idx] for idx in subset]
# Hacked fix to bug in Matplotlib that adds a bogus entry here
axes.legend(handles, labels, loc="upper left", framealpha=1)
def text_labels(
self,
gmeq: Eq,
varphi_: float,
px_: float,
pz_: float,
rdotx_: float,
rdotz_: float,
zoom_factor: float,
do_text_labels: bool,
) -> None:
"""Annotate with some text labels."""
xy_ = (2.5, -2) if zoom_factor >= 1 else (1.25, 0.9)
plt.text(
*xy_,
rf"$\varphi={varphi_}\quad\eta={gmeq.eta_}$",
horizontalalignment="center",
verticalalignment="center",
fontsize=14,
color="k",
)
if do_text_labels:
plt.text(
rdotx_ * 0.97,
rdotz_ + 0.2,
r"$\mathbf{v}$",
horizontalalignment="center",
verticalalignment="center",
fontsize=15,
color="r",
)
sf = 1.2 if varphi_ >= 0.5 else 0.85
plt.text(
px_ + 0.25,
pz_ * sf,
r"$\mathbf{\widetilde{p}}$",
horizontalalignment="center",
verticalalignment="center",
fontsize=15,
color="b",
)
def arrows(
self, px_: float, pz_: float, rdotx_: float, rdotz_: float
) -> None:
"""Annotate with some arrows."""
p_ = np.sqrt(px_ ** 2 + pz_ ** 2)
# Arrow for rdot direction
plt.arrow(
0,
0,
rdotx_,
rdotz_,
head_width=0.08,
head_length=0.16,
lw=1,
length_includes_head=True,
ec="r",
fc="r",
)
# Fishbone for p direction
np_ = int(0.5 + ((p_) * 5)) if p_ >= 0.2 else 1
hw_ = 0.2 # if do_half else 0.2
plt.arrow(
px_,
pz_,
-px_,
-pz_,
color="b",
head_width=hw_,
head_length=-0.1,
lw=1,
shape="full",
overhang=1,
length_includes_head=True,
head_starts_at_zero=False,
ec="b",
)
for i_head in list(range(1, np_)):
len_head = i_head / (np_)
plt.arrow(
0,
0,
px_ * len_head,
pz_ * len_head,
head_width=hw_,
head_length=0,
lw=1,
shape="full",
overhang=0,
length_includes_head=True,
ec="b",
)
len_head = 1
plt.arrow(
0,
0,
px_ * len_head,
pz_ * len_head,
head_width=hw_ * 2.5,
head_length=0,
lw=2,
shape="full",
overhang=0,
length_includes_head=True,
ec="b",
)
def lines_and_points(
self,
pd: Dict,
axes: Axes,
zoomx: np.ndarray,
do_pz: bool,
do_shapes: bool,
) -> None:
"""Plot some lines and points."""
# Unpack
(n_vertices_, ls_) = (pd["n_vertices"], pd["ls"])
(px_, pz_, rdotx_, rdotz_) = (
pd["px"],
pd["pz"],
pd["rdotx"],
pd["rdotz"],
)
psqrd_ = px_ ** 2 + pz_ ** 2
plt.plot(
(px_ / psqrd_, rdotx_), (pz_ / psqrd_, rdotz_), c="r", ls=ls_, lw=1
)
plt.plot((0, px_), (0, pz_), c="b", ls=ls_, lw=1)
if do_pz:
plt.plot((zoomx[0], zoomx[1]), (pz_, pz_), c="b", ls=":", lw=1)
if psqrd_ < 1:
plt.plot(
(px_, px_ / psqrd_), (pz_, pz_ / psqrd_), c="b", ls=ls_, lw=1
)
if do_shapes:
axes.add_patch(
RegularPolygon(
(px_, pz_), n_vertices_, radius=0.08, lw=1, ec="k", fc="b"
)
)
axes.add_patch(
RegularPolygon(
(rdotx_, rdotz_),
n_vertices_,
radius=0.08,
lw=1,
ec="k",
fc="r",
)
)
else:
axes.add_patch(
Circle((px_, pz_), radius=0.04, lw=1, ec="k", fc="b")
)
axes.add_patch(
Circle((rdotx_, rdotz_), radius=0.04, lw=1, ec="k", fc="r")
)
def annotations(self, axes: Axes, beta_: float, tanalpha_: float) -> None:
"""Do some more annotations."""
# alpha arc
plt.text(
0.45,
-0.05,
r"$\alpha$",
color="DarkRed",
# transform=axes.transAxes,
fontsize=12,
horizontalalignment="center",
verticalalignment="center",
)
axes.add_patch(
mpatches.Arc(
(0, 0),
1.2,
1.2,
color="DarkRed",
linewidth=0.5,
fill=False,
zorder=2,
theta1=270,
theta2=90 + np.rad2deg(np.arctan(tanalpha_)),
)
)
# beta arc
plt.text(
0.08,
-0.30,
r"$\beta$",
color="DarkBlue",
# transform=axes.transAxes,
fontsize=10,
horizontalalignment="center",
verticalalignment="center",
)
axes.add_patch(
mpatches.Arc(
(0, 0),
0.9,
0.9,
color="DarkBlue",
linewidth=0.5,
fill=False,
zorder=2,
theta1=270,
theta2=270 + np.rad2deg(beta_),
)
)
# "faster" direction
plt.text(
3.05,
1.6,
"faster",
color="r", # transform=axes.transAxes,
fontsize=12,
rotation=55,
horizontalalignment="center",
verticalalignment="center",
)
# "faster" direction
plt.text(
1.03,
-2,
"slower",
color="b", # transform=axes.transAxes,
fontsize=12,
rotation=-85,
horizontalalignment="center",
verticalalignment="center",
)
def legend(
self,
gmeq: Eq,
axes: Axes,
do_legend: bool,
do_half: bool,
do_ray_slowness: bool = False,
) -> None:
"""Construct and place a legend."""
if not do_legend:
return
handles, labels = axes.get_legend_handles_labels()
if gmeq.eta_ >= 1:
loc_ = (
"center right"
if do_half
else "upper left"
if do_ray_slowness
else "lower left"
)
else:
loc_ = (
"upper right"
if do_half
else "upper left"
if do_ray_slowness
else "lower left"
)
axes.legend(handles[::-1], labels[::-1], loc=loc_)
def figuratrix(
self,
gmeq: Eq,
varphi_: float,
n_points: int,
pz_min_: float = 1e-5,
pz_max_: float = 50,
) -> Tuple[np.ndarray, np.ndarray, Eq]:
"""Generate figuratrix."""
px_pz_eqn = Eq(
px, factor(gmeq.fgtx_px_pz_varphi_eqn.rhs.subs({varphi: varphi_}))
)
px_pz_lambda = lambdify([pz], re(N(px_pz_eqn.rhs)))
fgtx_pz_array = -np.power(
10, np.linspace(np.log10(pz_max_), np.log10(pz_min_), n_points)
)
# fgtx_px_array = np.array([float(re(N(px_pz_eqn.rhs.subs({pz:pz_}))))
# for pz_ in fgtx_pz_array])
fgtx_px_array = np.array(
[float(px_pz_lambda(pz_)) for pz_ in fgtx_pz_array]
)
return fgtx_px_array, fgtx_pz_array, px_pz_eqn
def indicatrix(
self,
gmeq: Eq,
varphi_: float,
n_points: int,
pz_min_: float = 1e-5,
pz_max_: float = 300,
) -> Tuple[np.ndarray, np.ndarray, Eq, Eq]:
"""Generate figuratrix."""
rdotx_pz_eqn = gmeq.idtx_rdotx_pz_varphi_eqn.subs({varphi: varphi_})
rdotz_pz_eqn = gmeq.idtx_rdotz_pz_varphi_eqn.subs({varphi: varphi_})
rdotx_pz_lambda = lambdify([pz], re(N(rdotx_pz_eqn.rhs)))
rdotz_pz_lambda = lambdify([pz], re(N(rdotz_pz_eqn.rhs)))
fgtx_pz_array = -np.power(
10, np.linspace(np.log10(pz_max_), np.log10(pz_min_), n_points)
)
# idtx_rdotx_array \
# = np.array([float(re(N(rdotx_pz_eqn.rhs.subs({pz:pz_}))))
# for pz_ in fgtx_pz_array])
# idtx_rdotz_array \
# = np.array([float(re(N(rdotz_pz_eqn.rhs.subs({pz:pz_}))))
# for pz_ in fgtx_pz_array])
idtx_rdotx_array = np.array(
[float(rdotx_pz_lambda(pz_)) for pz_ in fgtx_pz_array]
)
idtx_rdotz_array = np.array(
[float(rdotz_pz_lambda(pz_)) for pz_ in fgtx_pz_array]
)
return idtx_rdotx_array, idtx_rdotz_array, rdotx_pz_eqn, rdotz_pz_eqn
def plot_figuratrix(
self,
fgtx_px_array: np.ndarray,
fgtx_pz_array: np.ndarray,
maybe_recip_fn: Callable,
do_ray_slowness: bool = False,
) -> None:
"""Plot figuratrix."""
# label = r'normal speed' if do_ray_slowness else r'figuratrix $F^*$'
label = r"normal velocity" if do_ray_slowness else r"normal slowness"
plt.plot(
*maybe_recip_fn(-fgtx_px_array, fgtx_pz_array),
lw=2,
c="DarkBlue",
ls="-",
label=label,
)
plt.plot(
*maybe_recip_fn(fgtx_px_array, fgtx_pz_array),
lw=2,
c="DarkBlue",
ls="-",
)
def plot_indicatrix(
self,
idtx_rdotx_array: np.ndarray,
idtx_rdotz_array: np.ndarray,
maybe_recip_fn: Callable,
do_ray_slowness: bool = False,
) -> None:
"""Plot indicatrix."""
# label = r'ray slowness' if do_ray_slowness else r'indicatrix $F$'
label = r"ray slowness" if do_ray_slowness else r"ray velocity"
plt.plot(
*maybe_recip_fn(idtx_rdotx_array, idtx_rdotz_array),
lw=2,
c="DarkRed",
ls="-",
label=label,
)
plt.plot(
*maybe_recip_fn(-idtx_rdotx_array, idtx_rdotz_array),
lw=2,
c="DarkRed",
ls="-",
)
def plot_unit_circle(self, varphi_: float, do_varphi_circle: bool) -> None:
"""Plot unit circle as a reference for indicatrix/figuratrix."""
unit_circle_beta_array = np.linspace(0, np.pi)
plt.plot(
np.cos(unit_circle_beta_array * 2),
np.sin(unit_circle_beta_array * 2),
lw=1,
c="g",
ls="-",
label="unit circle",
)
if do_varphi_circle:
plt.plot(
varphi_ * np.cos(unit_circle_beta_array * 2),
varphi_ * np.sin(unit_circle_beta_array * 2),
lw=1,
c="g",
ls=":",
label=rf"$\varphi={varphi_}$",
)
def relative_geometry(
self,
gmeq: Eq,
name: str,
fig_size: Tuple[float, float] = None,
dpi: float = None,
varphi_: float = 1,
zoom_factor: float = 1,
do_half: bool = False,
do_legend: bool = True,
do_text_labels: bool = True,
do_arrows: bool = True,
do_lines_points: bool = True,
do_shapes: bool = False,
do_varphi_circle: bool = False,
do_pz: bool = False,
do_ray_slowness: bool = False,
x_max: float = 3.4,
n_points: int = 100,
pz_min_: float = 1e-1,
) -> None:
r"""
Plot indicatrix relative geometry.
Plot the loci of :math:`\mathbf{\widetilde{p}}` and :math:`\mathbf{r}`
and their behavior defined by :math:`F` relative to the :math:`\xi`
circle.
Args:
gmeq:
GME model equations class instance defined in
:mod:`gme.core.equations`
varphi_choice:
the value of :math:`\varphi` to use
zoom_factor:
fractional zoom factor relative to preassigned graph limits
do_half:
plot only for :math:`x\geq0`?
do_annotations:
plot annotated arcs, faster/slower arrows?
do_legend:
display the legend?
do_text_labels:
display text annotations?
do_arrows:
display vector/covector arrows?
do_lines_points:
display dashed/dotted tangent lines etc?
do_shapes:
plot key points using polygon symbols
rather than simple circles
do_varphi_circle :
plot the :math:`\xi` (typically unit) circle?
do_pz:
plot horizontal dotted line indicating magnitude of :math:`p_z`
do_ray_slowness:
invert ray speed (but keep ray direction) in indicatrix?
"""
# Create figure
_ = self.create_figure(name, fig_size=fig_size, dpi=dpi)
# Adjust plot scale, limits
axes: Axes = plt.gca()
axes.set_aspect(1)
plt.grid(True, ls=":")
x_min: float = -0.1 if do_half else -x_max
y_minmax: float = 2.4 if gmeq.eta_ >= 1 else 2.4
zoomx = np.array([x_min, x_max]) * zoom_factor
zoomz = np.array([-y_minmax, y_minmax]) * zoom_factor
plt.xlim(zoomx)
plt.ylim(zoomz)
plt.xlabel(r"Horizontal component")
plt.ylabel(r"Vertical component")
# Prep
def recip_fn(x_, z_):
return [x_ / (x_ ** 2 + z_ ** 2), z_ / (x_ ** 2 + z_ ** 2)]
def null_fn(x_, z_):
return [x_, z_]
maybe_recip_fn = recip_fn if do_ray_slowness else null_fn
points_tangents_dicts = {
0.1: {"n_vertices": 3, "ls": ":", "pz_min": pz_min, "pz_max": 1000},
0.15: {
"n_vertices": 3,
"ls": ":",
"pz_min": pz_min_,
"pz_max": 1000,
},
0.5: {
"n_vertices": 4,
"ls": "--",
"pz_min": pz_min_,
"pz_max": 100,
},
1: {"n_vertices": 4, "ls": "--", "pz_min": pz_min_, "pz_max": 100},
1.3: {"n_vertices": 5, "ls": "-.", "pz_min": pz_min_, "pz_max": 10},
2: {"n_vertices": 5, "ls": "-.", "pz_min": pz_min_, "pz_max": 10},
3: {"n_vertices": 5, "ls": "-.", "pz_min": pz_min_, "pz_max": 3},
}
# Compute some stuff
pdict = points_tangents_dicts[varphi_]
fgtx_px_array, fgtx_pz_array, px_pz_eqn = self.figuratrix(
gmeq, varphi_, n_points
)
(
idtx_rdotx_array,
idtx_rdotz_array,
rdotx_pz_eqn,
rdotz_pz_eqn,
) = self.indicatrix(
gmeq,
varphi_,
n_points,
pz_min_=pdict["pz_min"],
pz_max_=pdict["pz_max"],
)
pz_ = -np.cos(np.pi / 4)
px_ = float(N(re(px_pz_eqn.rhs.subs({pz: pz_}))))
rdotx_ = float(re(rdotx_pz_eqn.rhs.subs({pz: pz_})))
rdotz_ = float(re(rdotz_pz_eqn.rhs.subs({pz: pz_})))
# tanalpha_ = (-rdotx_/rdotz_)
pdict.update(
{
"varphi": varphi_,
"px": px_,
"pz": pz_,
"rdotx": rdotx_,
"rdotz": rdotz_,
}
)
# Do the plotting
self.plot_indicatrix(
idtx_rdotx_array, idtx_rdotz_array, maybe_recip_fn, do_ray_slowness
)
self.plot_figuratrix(
fgtx_px_array, fgtx_pz_array, maybe_recip_fn, do_ray_slowness
)
self.plot_unit_circle(varphi_, do_varphi_circle)
if do_lines_points:
self.lines_and_points(pdict, axes, zoomx, do_pz, do_shapes)
self.text_labels(
gmeq, varphi_, px_, pz_, rdotx_, rdotz_, zoom_factor, do_text_labels
)
if do_arrows:
self.arrows(px_, pz_, rdotx_, rdotz_)
# if do_annotations: self.annotations(axes, beta_, tanalpha_)
self.legend(gmeq, axes, do_legend, do_half, do_ray_slowness)