Chapter 1: Introductions#

two_period_job_search.py#

Hide code cell source
from quantecon.distributions import BetaBinomial

import numpy as np
from numba import njit
from collections import namedtuple


# NamedTuple Model
Model = namedtuple("Model", ("n", "w_vals", "φ", "β", "c"))


def create_job_search_model(
        n=50,        # wage grid size
        w_min=10.0,  # lowest wage
        w_max=60.0,  # highest wage
        a=200,       # wage distribution parameter
        b=100,       # wage distribution parameter
        β=0.96,      # discount factor
        c=10.0       # unemployment compensation
    ):
    """
    Creates the parameters for job search model and returns the
    instance of namedtuple Model
    """
    w_vals = np.linspace(w_min, w_max, n+1)
    φ = BetaBinomial(n, a, b).pdf()
    return Model(n=n, w_vals=w_vals, φ=φ, β=β, c=c)


@njit
def v_1(w, model):
    """
    Computes lifetime value at t=1 given current wage w_1 = w
    """
    β, c = model.β, model.c
    s = np.maximum(c, model.w_vals)
    h_1 = c + β * np.sum(s * model.φ)
    return np.maximum(w + β * w, h_1)


@njit
def res_wage(model):
    """
    Computes reservation wage at t=1
    """
    β, c = model.β, model.c
    s = np.maximum(c, model.w_vals)
    h_1 = c + β * np.sum(s * model.φ)
    return h_1 / (1 + β)



##### Plots #####

import matplotlib.pyplot as plt
import matplotlib.pyplot as plt

plt.rcParams.update({"text.usetex": True, "font.size": 14})


default_model = create_job_search_model()


def fig_dist(model=default_model, fs=10):
    """
    Plot the distribution of wages
    """
    fig, ax = plt.subplots()
    ax.plot(model.w_vals, model.φ, "-o", alpha=0.5, label="wage distribution")
    ax.legend(loc="upper left", fontsize=fs)


def fig_v1(model=default_model, savefig=False,
                  figname="figures/iid_job_search_0_py.pdf", fs=18):
    """
    Plot two-period value function and res wage
    """
    n, w_vals, φ, β, c = model

    v = [v_1(w, model) for w in w_vals]
    w_star = res_wage(model)
    s = np.maximum(c, w_vals)
    continuation_val = c + β * np.sum(s * φ)
    min_w, max_w = np.min(w_vals), np.max(w_vals)

    fontdict = {'fontsize': 10}
    fig, ax = plt.subplots(figsize=(9, 5.5))
    ax.set_ylim(0, 120)
    ax.set_xlim(min_w, max_w)
    ax.vlines((w_star,), (0,), (continuation_val,), lw=0.5)
    ax.set_yticks((0, 50, 100))
    ax.set_yticklabels((0, 50, 100), fontdict=fontdict)
    ax.set_xticks((min_w, w_star, max_w))
    ax.set_xticklabels((min_w, r"$w^*_1$", max_w), fontdict=fontdict)
    ax.plot(w_vals, w_vals + β * w_vals, alpha=0.8, linewidth=3,
            label=r"$w_1 + \beta w_1$")
    ax.plot(w_vals, [continuation_val]*(n+1), linewidth=3, alpha=0.8,
            label=r"$c + \beta \sum_{w'} \max\{c, w'\} \varphi(w')$" )
    ax.plot(w_vals, v, "k--", markersize=2, alpha=1.0, linewidth=2,
            label=r"$v_1(w_1)$")
    ax.legend(frameon=False, fontsize=fs, loc="upper left")
    if savefig:
        fig.savefig(figname)
fig_v1()
Error in callback <function _draw_all_if_interactive at 0x7f58bf0c5870> (for post_execute):
---------------------------------------------------------------------------
FileNotFoundError                         Traceback (most recent call last)
File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/texmanager.py:255, in TexManager._run_checked_subprocess(cls, command, tex, cwd)
    254 try:
--> 255     report = subprocess.check_output(
    256         command, cwd=cwd if cwd is not None else cls.texcache,
    257         stderr=subprocess.STDOUT)
    258 except FileNotFoundError as exc:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/subprocess.py:421, in check_output(timeout, *popenargs, **kwargs)
    419     kwargs['input'] = empty
--> 421 return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
    422            **kwargs).stdout

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/subprocess.py:503, in run(input, capture_output, timeout, check, *popenargs, **kwargs)
    501     kwargs['stderr'] = PIPE
--> 503 with Popen(*popenargs, **kwargs) as process:
    504     try:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/subprocess.py:971, in Popen.__init__(self, args, bufsize, executable, stdin, stdout, stderr, preexec_fn, close_fds, shell, cwd, env, universal_newlines, startupinfo, creationflags, restore_signals, start_new_session, pass_fds, user, group, extra_groups, encoding, errors, text, umask, pipesize)
    968             self.stderr = io.TextIOWrapper(self.stderr,
    969                     encoding=encoding, errors=errors)
--> 971     self._execute_child(args, executable, preexec_fn, close_fds,
    972                         pass_fds, cwd, env,
    973                         startupinfo, creationflags, shell,
    974                         p2cread, p2cwrite,
    975                         c2pread, c2pwrite,
    976                         errread, errwrite,
    977                         restore_signals,
    978                         gid, gids, uid, umask,
    979                         start_new_session)
    980 except:
    981     # Cleanup if the child failed starting.

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/subprocess.py:1863, in Popen._execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session)
   1862         err_msg = os.strerror(errno_num)
-> 1863     raise child_exception_type(errno_num, err_msg, err_filename)
   1864 raise child_exception_type(err_msg)

FileNotFoundError: [Errno 2] No such file or directory: 'latex'

The above exception was the direct cause of the following exception:

RuntimeError                              Traceback (most recent call last)
File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/pyplot.py:120, in _draw_all_if_interactive()
    118 def _draw_all_if_interactive():
    119     if matplotlib.is_interactive():
--> 120         draw_all()

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/_pylab_helpers.py:132, in Gcf.draw_all(cls, force)
    130 for manager in cls.get_all_fig_managers():
    131     if force or manager.canvas.figure.stale:
--> 132         manager.canvas.draw_idle()

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/backend_bases.py:2082, in FigureCanvasBase.draw_idle(self, *args, **kwargs)
   2080 if not self._is_idle_drawing:
   2081     with self._idle_draw_cntx():
-> 2082         self.draw(*args, **kwargs)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/backends/backend_agg.py:400, in FigureCanvasAgg.draw(self)
    396 # Acquire a lock on the shared font cache.
    397 with RendererAgg.lock, \
    398      (self.toolbar._wait_cursor_for_draw_cm() if self.toolbar
    399       else nullcontext()):
--> 400     self.figure.draw(self.renderer)
    401     # A GUI class may be need to update a window using this draw, so
    402     # don't forget to call the superclass.
    403     super().draw()

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/artist.py:95, in _finalize_rasterization.<locals>.draw_wrapper(artist, renderer, *args, **kwargs)
     93 @wraps(draw)
     94 def draw_wrapper(artist, renderer, *args, **kwargs):
---> 95     result = draw(artist, renderer, *args, **kwargs)
     96     if renderer._rasterizing:
     97         renderer.stop_rasterizing()

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/artist.py:72, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
     69     if artist.get_agg_filter() is not None:
     70         renderer.start_filter()
---> 72     return draw(artist, renderer)
     73 finally:
     74     if artist.get_agg_filter() is not None:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/figure.py:3140, in Figure.draw(self, renderer)
   3137         # ValueError can occur when resizing a window.
   3139 self.patch.draw(renderer)
-> 3140 mimage._draw_list_compositing_images(
   3141     renderer, self, artists, self.suppressComposite)
   3143 for sfig in self.subfigs:
   3144     sfig.draw(renderer)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/image.py:131, in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
    129 if not_composite or not has_images:
    130     for a in artists:
--> 131         a.draw(renderer)
    132 else:
    133     # Composite any adjacent images together
    134     image_group = []

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/artist.py:72, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
     69     if artist.get_agg_filter() is not None:
     70         renderer.start_filter()
---> 72     return draw(artist, renderer)
     73 finally:
     74     if artist.get_agg_filter() is not None:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/axes/_base.py:3064, in _AxesBase.draw(self, renderer)
   3061 if artists_rasterized:
   3062     _draw_rasterized(self.figure, artists_rasterized, renderer)
-> 3064 mimage._draw_list_compositing_images(
   3065     renderer, self, artists, self.figure.suppressComposite)
   3067 renderer.close_group('axes')
   3068 self.stale = False

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/image.py:131, in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
    129 if not_composite or not has_images:
    130     for a in artists:
--> 131         a.draw(renderer)
    132 else:
    133     # Composite any adjacent images together
    134     image_group = []

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/artist.py:72, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
     69     if artist.get_agg_filter() is not None:
     70         renderer.start_filter()
---> 72     return draw(artist, renderer)
     73 finally:
     74     if artist.get_agg_filter() is not None:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/axis.py:1377, in Axis.draw(self, renderer, *args, **kwargs)
   1374 renderer.open_group(__name__, gid=self.get_gid())
   1376 ticks_to_draw = self._update_ticks()
-> 1377 tlb1, tlb2 = self._get_ticklabel_bboxes(ticks_to_draw, renderer)
   1379 for tick in ticks_to_draw:
   1380     tick.draw(renderer)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/axis.py:1304, in Axis._get_ticklabel_bboxes(self, ticks, renderer)
   1302 if renderer is None:
   1303     renderer = self.figure._get_renderer()
-> 1304 return ([tick.label1.get_window_extent(renderer)
   1305          for tick in ticks if tick.label1.get_visible()],
   1306         [tick.label2.get_window_extent(renderer)
   1307          for tick in ticks if tick.label2.get_visible()])

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/axis.py:1304, in <listcomp>(.0)
   1302 if renderer is None:
   1303     renderer = self.figure._get_renderer()
-> 1304 return ([tick.label1.get_window_extent(renderer)
   1305          for tick in ticks if tick.label1.get_visible()],
   1306         [tick.label2.get_window_extent(renderer)
   1307          for tick in ticks if tick.label2.get_visible()])

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/text.py:959, in Text.get_window_extent(self, renderer, dpi)
    954     raise RuntimeError(
    955         "Cannot get window extent of text w/o renderer. You likely "
    956         "want to call 'figure.draw_without_rendering()' first.")
    958 with cbook._setattr_cm(self.figure, dpi=dpi):
--> 959     bbox, info, descent = self._get_layout(self._renderer)
    960     x, y = self.get_unitless_position()
    961     x, y = self.get_transform().transform((x, y))

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/text.py:378, in Text._get_layout(self, renderer)
    375 ys = []
    377 # Full vertical extent of font, including ascenders and descenders:
--> 378 _, lp_h, lp_d = _get_text_metrics_with_cache(
    379     renderer, "lp", self._fontproperties,
    380     ismath="TeX" if self.get_usetex() else False, dpi=self.figure.dpi)
    381 min_dy = (lp_h - lp_d) * self._linespacing
    383 for i, line in enumerate(lines):

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/text.py:97, in _get_text_metrics_with_cache(renderer, text, fontprop, ismath, dpi)
     94 """Call ``renderer.get_text_width_height_descent``, caching the results."""
     95 # Cached based on a copy of fontprop so that later in-place mutations of
     96 # the passed-in argument do not mess up the cache.
---> 97 return _get_text_metrics_with_cache_impl(
     98     weakref.ref(renderer), text, fontprop.copy(), ismath, dpi)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/text.py:105, in _get_text_metrics_with_cache_impl(renderer_ref, text, fontprop, ismath, dpi)
    101 @functools.lru_cache(4096)
    102 def _get_text_metrics_with_cache_impl(
    103         renderer_ref, text, fontprop, ismath, dpi):
    104     # dpi is unused, but participates in cache invalidation (via the renderer).
--> 105     return renderer_ref().get_text_width_height_descent(text, fontprop, ismath)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/backends/backend_agg.py:226, in RendererAgg.get_text_width_height_descent(self, s, prop, ismath)
    224 _api.check_in_list(["TeX", True, False], ismath=ismath)
    225 if ismath == "TeX":
--> 226     return super().get_text_width_height_descent(s, prop, ismath)
    228 if ismath:
    229     ox, oy, width, height, descent, font_image = \
    230         self.mathtext_parser.parse(s, self.dpi, prop)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/backend_bases.py:645, in RendererBase.get_text_width_height_descent(self, s, prop, ismath)
    641 fontsize = prop.get_size_in_points()
    643 if ismath == 'TeX':
    644     # todo: handle properties
--> 645     return self.get_texmanager().get_text_width_height_descent(
    646         s, fontsize, renderer=self)
    648 dpi = self.points_to_pixels(72)
    649 if ismath:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/texmanager.py:368, in TexManager.get_text_width_height_descent(cls, tex, fontsize, renderer)
    366 if tex.strip() == '':
    367     return 0, 0, 0
--> 368 dvifile = cls.make_dvi(tex, fontsize)
    369 dpi_fraction = renderer.points_to_pixels(1.) if renderer else 1
    370 with dviread.Dvi(dvifile, 72 * dpi_fraction) as dvi:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/texmanager.py:300, in TexManager.make_dvi(cls, tex, fontsize)
    298     with TemporaryDirectory(dir=cwd) as tmpdir:
    299         tmppath = Path(tmpdir)
--> 300         cls._run_checked_subprocess(
    301             ["latex", "-interaction=nonstopmode", "--halt-on-error",
    302              f"--output-directory={tmppath.name}",
    303              f"{texfile.name}"], tex, cwd=cwd)
    304         (tmppath / Path(dvifile).name).replace(dvifile)
    305 return dvifile

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/texmanager.py:259, in TexManager._run_checked_subprocess(cls, command, tex, cwd)
    255     report = subprocess.check_output(
    256         command, cwd=cwd if cwd is not None else cls.texcache,
    257         stderr=subprocess.STDOUT)
    258 except FileNotFoundError as exc:
--> 259     raise RuntimeError(
    260         'Failed to process string with tex because {} could not be '
    261         'found'.format(command[0])) from exc
    262 except subprocess.CalledProcessError as exc:
    263     raise RuntimeError(
    264         '{prog} was not able to process the following string:\n'
    265         '{tex!r}\n\n'
   (...)
    272             exc=exc.output.decode('utf-8', 'backslashreplace'))
    273         ) from None

RuntimeError: Failed to process string with tex because latex could not be found
---------------------------------------------------------------------------
FileNotFoundError                         Traceback (most recent call last)
File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/texmanager.py:255, in TexManager._run_checked_subprocess(cls, command, tex, cwd)
    254 try:
--> 255     report = subprocess.check_output(
    256         command, cwd=cwd if cwd is not None else cls.texcache,
    257         stderr=subprocess.STDOUT)
    258 except FileNotFoundError as exc:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/subprocess.py:421, in check_output(timeout, *popenargs, **kwargs)
    419     kwargs['input'] = empty
--> 421 return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
    422            **kwargs).stdout

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/subprocess.py:503, in run(input, capture_output, timeout, check, *popenargs, **kwargs)
    501     kwargs['stderr'] = PIPE
--> 503 with Popen(*popenargs, **kwargs) as process:
    504     try:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/subprocess.py:971, in Popen.__init__(self, args, bufsize, executable, stdin, stdout, stderr, preexec_fn, close_fds, shell, cwd, env, universal_newlines, startupinfo, creationflags, restore_signals, start_new_session, pass_fds, user, group, extra_groups, encoding, errors, text, umask, pipesize)
    968             self.stderr = io.TextIOWrapper(self.stderr,
    969                     encoding=encoding, errors=errors)
--> 971     self._execute_child(args, executable, preexec_fn, close_fds,
    972                         pass_fds, cwd, env,
    973                         startupinfo, creationflags, shell,
    974                         p2cread, p2cwrite,
    975                         c2pread, c2pwrite,
    976                         errread, errwrite,
    977                         restore_signals,
    978                         gid, gids, uid, umask,
    979                         start_new_session)
    980 except:
    981     # Cleanup if the child failed starting.

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/subprocess.py:1863, in Popen._execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session)
   1862         err_msg = os.strerror(errno_num)
-> 1863     raise child_exception_type(errno_num, err_msg, err_filename)
   1864 raise child_exception_type(err_msg)

FileNotFoundError: [Errno 2] No such file or directory: 'latex'

The above exception was the direct cause of the following exception:

RuntimeError                              Traceback (most recent call last)
File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/IPython/core/formatters.py:340, in BaseFormatter.__call__(self, obj)
    338     pass
    339 else:
--> 340     return printer(obj)
    341 # Finally look for special method names
    342 method = get_real_method(obj, self.print_method)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/IPython/core/pylabtools.py:152, in print_figure(fig, fmt, bbox_inches, base64, **kwargs)
    149     from matplotlib.backend_bases import FigureCanvasBase
    150     FigureCanvasBase(fig)
--> 152 fig.canvas.print_figure(bytes_io, **kw)
    153 data = bytes_io.getvalue()
    154 if fmt == 'svg':

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/backend_bases.py:2342, in FigureCanvasBase.print_figure(self, filename, dpi, facecolor, edgecolor, orientation, format, bbox_inches, pad_inches, bbox_extra_artists, backend, **kwargs)
   2336     renderer = _get_renderer(
   2337         self.figure,
   2338         functools.partial(
   2339             print_method, orientation=orientation)
   2340     )
   2341     with getattr(renderer, "_draw_disabled", nullcontext)():
-> 2342         self.figure.draw(renderer)
   2344 if bbox_inches:
   2345     if bbox_inches == "tight":

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/artist.py:95, in _finalize_rasterization.<locals>.draw_wrapper(artist, renderer, *args, **kwargs)
     93 @wraps(draw)
     94 def draw_wrapper(artist, renderer, *args, **kwargs):
---> 95     result = draw(artist, renderer, *args, **kwargs)
     96     if renderer._rasterizing:
     97         renderer.stop_rasterizing()

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/artist.py:72, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
     69     if artist.get_agg_filter() is not None:
     70         renderer.start_filter()
---> 72     return draw(artist, renderer)
     73 finally:
     74     if artist.get_agg_filter() is not None:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/figure.py:3140, in Figure.draw(self, renderer)
   3137         # ValueError can occur when resizing a window.
   3139 self.patch.draw(renderer)
-> 3140 mimage._draw_list_compositing_images(
   3141     renderer, self, artists, self.suppressComposite)
   3143 for sfig in self.subfigs:
   3144     sfig.draw(renderer)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/image.py:131, in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
    129 if not_composite or not has_images:
    130     for a in artists:
--> 131         a.draw(renderer)
    132 else:
    133     # Composite any adjacent images together
    134     image_group = []

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/artist.py:72, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
     69     if artist.get_agg_filter() is not None:
     70         renderer.start_filter()
---> 72     return draw(artist, renderer)
     73 finally:
     74     if artist.get_agg_filter() is not None:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/axes/_base.py:3064, in _AxesBase.draw(self, renderer)
   3061 if artists_rasterized:
   3062     _draw_rasterized(self.figure, artists_rasterized, renderer)
-> 3064 mimage._draw_list_compositing_images(
   3065     renderer, self, artists, self.figure.suppressComposite)
   3067 renderer.close_group('axes')
   3068 self.stale = False

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/image.py:131, in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
    129 if not_composite or not has_images:
    130     for a in artists:
--> 131         a.draw(renderer)
    132 else:
    133     # Composite any adjacent images together
    134     image_group = []

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/artist.py:72, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
     69     if artist.get_agg_filter() is not None:
     70         renderer.start_filter()
---> 72     return draw(artist, renderer)
     73 finally:
     74     if artist.get_agg_filter() is not None:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/axis.py:1377, in Axis.draw(self, renderer, *args, **kwargs)
   1374 renderer.open_group(__name__, gid=self.get_gid())
   1376 ticks_to_draw = self._update_ticks()
-> 1377 tlb1, tlb2 = self._get_ticklabel_bboxes(ticks_to_draw, renderer)
   1379 for tick in ticks_to_draw:
   1380     tick.draw(renderer)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/axis.py:1304, in Axis._get_ticklabel_bboxes(self, ticks, renderer)
   1302 if renderer is None:
   1303     renderer = self.figure._get_renderer()
-> 1304 return ([tick.label1.get_window_extent(renderer)
   1305          for tick in ticks if tick.label1.get_visible()],
   1306         [tick.label2.get_window_extent(renderer)
   1307          for tick in ticks if tick.label2.get_visible()])

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/axis.py:1304, in <listcomp>(.0)
   1302 if renderer is None:
   1303     renderer = self.figure._get_renderer()
-> 1304 return ([tick.label1.get_window_extent(renderer)
   1305          for tick in ticks if tick.label1.get_visible()],
   1306         [tick.label2.get_window_extent(renderer)
   1307          for tick in ticks if tick.label2.get_visible()])

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/text.py:959, in Text.get_window_extent(self, renderer, dpi)
    954     raise RuntimeError(
    955         "Cannot get window extent of text w/o renderer. You likely "
    956         "want to call 'figure.draw_without_rendering()' first.")
    958 with cbook._setattr_cm(self.figure, dpi=dpi):
--> 959     bbox, info, descent = self._get_layout(self._renderer)
    960     x, y = self.get_unitless_position()
    961     x, y = self.get_transform().transform((x, y))

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/text.py:378, in Text._get_layout(self, renderer)
    375 ys = []
    377 # Full vertical extent of font, including ascenders and descenders:
--> 378 _, lp_h, lp_d = _get_text_metrics_with_cache(
    379     renderer, "lp", self._fontproperties,
    380     ismath="TeX" if self.get_usetex() else False, dpi=self.figure.dpi)
    381 min_dy = (lp_h - lp_d) * self._linespacing
    383 for i, line in enumerate(lines):

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/text.py:97, in _get_text_metrics_with_cache(renderer, text, fontprop, ismath, dpi)
     94 """Call ``renderer.get_text_width_height_descent``, caching the results."""
     95 # Cached based on a copy of fontprop so that later in-place mutations of
     96 # the passed-in argument do not mess up the cache.
---> 97 return _get_text_metrics_with_cache_impl(
     98     weakref.ref(renderer), text, fontprop.copy(), ismath, dpi)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/text.py:105, in _get_text_metrics_with_cache_impl(renderer_ref, text, fontprop, ismath, dpi)
    101 @functools.lru_cache(4096)
    102 def _get_text_metrics_with_cache_impl(
    103         renderer_ref, text, fontprop, ismath, dpi):
    104     # dpi is unused, but participates in cache invalidation (via the renderer).
--> 105     return renderer_ref().get_text_width_height_descent(text, fontprop, ismath)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/backends/backend_agg.py:226, in RendererAgg.get_text_width_height_descent(self, s, prop, ismath)
    224 _api.check_in_list(["TeX", True, False], ismath=ismath)
    225 if ismath == "TeX":
--> 226     return super().get_text_width_height_descent(s, prop, ismath)
    228 if ismath:
    229     ox, oy, width, height, descent, font_image = \
    230         self.mathtext_parser.parse(s, self.dpi, prop)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/backend_bases.py:645, in RendererBase.get_text_width_height_descent(self, s, prop, ismath)
    641 fontsize = prop.get_size_in_points()
    643 if ismath == 'TeX':
    644     # todo: handle properties
--> 645     return self.get_texmanager().get_text_width_height_descent(
    646         s, fontsize, renderer=self)
    648 dpi = self.points_to_pixels(72)
    649 if ismath:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/texmanager.py:368, in TexManager.get_text_width_height_descent(cls, tex, fontsize, renderer)
    366 if tex.strip() == '':
    367     return 0, 0, 0
--> 368 dvifile = cls.make_dvi(tex, fontsize)
    369 dpi_fraction = renderer.points_to_pixels(1.) if renderer else 1
    370 with dviread.Dvi(dvifile, 72 * dpi_fraction) as dvi:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/texmanager.py:300, in TexManager.make_dvi(cls, tex, fontsize)
    298     with TemporaryDirectory(dir=cwd) as tmpdir:
    299         tmppath = Path(tmpdir)
--> 300         cls._run_checked_subprocess(
    301             ["latex", "-interaction=nonstopmode", "--halt-on-error",
    302              f"--output-directory={tmppath.name}",
    303              f"{texfile.name}"], tex, cwd=cwd)
    304         (tmppath / Path(dvifile).name).replace(dvifile)
    305 return dvifile

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/texmanager.py:259, in TexManager._run_checked_subprocess(cls, command, tex, cwd)
    255     report = subprocess.check_output(
    256         command, cwd=cwd if cwd is not None else cls.texcache,
    257         stderr=subprocess.STDOUT)
    258 except FileNotFoundError as exc:
--> 259     raise RuntimeError(
    260         'Failed to process string with tex because {} could not be '
    261         'found'.format(command[0])) from exc
    262 except subprocess.CalledProcessError as exc:
    263     raise RuntimeError(
    264         '{prog} was not able to process the following string:\n'
    265         '{tex!r}\n\n'
   (...)
    272             exc=exc.output.decode('utf-8', 'backslashreplace'))
    273         ) from None

RuntimeError: Failed to process string with tex because latex could not be found
<Figure size 900x550 with 1 Axes>

compute_spec_rad.py#

Hide code cell source
import numpy as np

# Spectral radius
ρ = lambda A: np.max(np.abs(np.linalg.eigvals(A)))

# Test with arbitrary A
A = np.array([
    [0.4, 0.1],
    [0.7, 0.2]
])
print(ρ(A))
0.5828427124746189

power_series.py#

Hide code cell source
import numpy as np

# Primitives
A = np.array([
    [0.4, 0.1],
    [0.7, 0.2]
])


# Method one: direct inverse
I = np.identity(2)
B_inverse = np.linalg.inv(I - A)


# Method two: power series
def power_series(A):
    B_sum = np.zeros((2, 2))
    A_power = np.identity(2)
    for k in range(50):
        B_sum += A_power
        A_power = np.dot(A_power, A)
    return B_sum


# Print maximal error
print(np.max(np.abs(B_inverse - power_series(A))))
5.6210591736771676e-12

s_approx.py#

Hide code cell source
"""
Computes the approximate fixed point of T via successive approximation.
"""

import numpy as np

def successive_approx(T,                     # Operator (callable)
                      x_0,                   # Initial condition
                      tolerance=1e-6,        # Error tolerance
                      max_iter=10_000,       # Max iteration bound
                      print_step=25):        # Print at multiples
    x = x_0
    error = tolerance + 1
    k = 1
    while (error > tolerance) and (k <= max_iter):
        x_new = T(x)
        error = np.max(np.abs(x_new - x))
        if k % print_step == 0:
            print(f"Completed iteration {k} with error {error}.")
        x = x_new
        k += 1
    if error <= tolerance:
        print(f"Terminated successfully in {k} iterations.")
    else:
        print("Warning: hit iteration bound.")
    return x

linear_iter.py#

Hide code cell source
from s_approx import successive_approx
import numpy as np

# Compute the fixed point of Tx = Ax + b via linear algebra
A = np.array([
    [0.4, 0.1],
    [0.7, 0.2]
])

b = np.array([
    [1.0],
    [2.0]
])

I = np.identity(2)
x_star = np.linalg.solve(I - A, b)  # compute (I - A)^{-1} * b


# Compute the fixed point via successive approximation
T = lambda x: np.dot(A, x) + b
x_0 = np.array([
    [1.0],
    [1.0]
])
x_star_approx = successive_approx(T, x_0)

# Test for approximate equality (prints "True")
print(np.allclose(x_star, x_star_approx, rtol=1e-5))
Completed iteration 25 with error 2.911659384707832e-06.
Terminated successfully in 28 iterations.
True

linear_iter_fig.py#

Hide code cell source
import matplotlib.pyplot as plt
import matplotlib.pyplot as plt

plt.rcParams.update({"text.usetex": True, "font.size": 14})
import numpy as np

from linear_iter import x_star, T


fig, ax = plt.subplots()

e = 0.02

marker_size = 60
fs = 10

colors = ("red", "blue", "orange", "green")
u_0_vecs = ([[2.0], [3.0]], [[3.0], [5.2]], [[2.4], [3.6]], [[2.6], [5.6]])
u_0_vecs = list(map(np.array, u_0_vecs))
iter_range = 8

for (x_0, color) in zip(u_0_vecs, colors):
    x = x_0
    s, t = x
    ax.text(s+e, t-4*e, r"$u_0$", fontsize=fs)

    for i in range(iter_range):
        s, t = x
        ax.scatter((s,), (t,), c=color, alpha=0.2, s=marker_size)
        x_new = T(x)
        s_new, t_new = x_new
        ax.plot((s, s_new), (t, t_new), marker='.',linewidth=0.5, alpha=0.5, color=color)
        x = x_new

s_star, t_star = x_star
ax.scatter((s_star,), (t_star,), c="k", s=marker_size * 1.2)
ax.text(s_star-4*e, t_star+4*e, r"$u^*$", fontsize=fs)

ax.set_xticks((2.0, 2.5, 3.0))
ax.set_yticks((3.0, 4.0, 5.0, 6.0))
ax.set_xlim(1.8, 3.2)
ax.set_ylim(2.8, 6.1)

fig.savefig("figures/linear_iter_fig_1.pdf")
Completed iteration 25 with error 2.911659384707832e-06.
Terminated successfully in 28 iterations.
True
---------------------------------------------------------------------------
FileNotFoundError                         Traceback (most recent call last)
Cell In[7], line 44
     41 ax.set_xlim(1.8, 3.2)
     42 ax.set_ylim(2.8, 6.1)
---> 44 fig.savefig("figures/linear_iter_fig_1.pdf")

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/figure.py:3343, in Figure.savefig(self, fname, transparent, **kwargs)
   3339     for ax in self.axes:
   3340         stack.enter_context(
   3341             ax.patch._cm_set(facecolor='none', edgecolor='none'))
-> 3343 self.canvas.print_figure(fname, **kwargs)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/backend_bases.py:2366, in FigureCanvasBase.print_figure(self, filename, dpi, facecolor, edgecolor, orientation, format, bbox_inches, pad_inches, bbox_extra_artists, backend, **kwargs)
   2362 try:
   2363     # _get_renderer may change the figure dpi (as vector formats
   2364     # force the figure dpi to 72), so we need to set it again here.
   2365     with cbook._setattr_cm(self.figure, dpi=dpi):
-> 2366         result = print_method(
   2367             filename,
   2368             facecolor=facecolor,
   2369             edgecolor=edgecolor,
   2370             orientation=orientation,
   2371             bbox_inches_restore=_bbox_inches_restore,
   2372             **kwargs)
   2373 finally:
   2374     if bbox_inches and restore_bbox:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/backend_bases.py:2232, in FigureCanvasBase._switch_canvas_and_return_print_method.<locals>.<lambda>(*args, **kwargs)
   2228     optional_kws = {  # Passed by print_figure for other renderers.
   2229         "dpi", "facecolor", "edgecolor", "orientation",
   2230         "bbox_inches_restore"}
   2231     skip = optional_kws - {*inspect.signature(meth).parameters}
-> 2232     print_method = functools.wraps(meth)(lambda *args, **kwargs: meth(
   2233         *args, **{k: v for k, v in kwargs.items() if k not in skip}))
   2234 else:  # Let third-parties do as they see fit.
   2235     print_method = meth

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/backends/backend_pdf.py:2808, in FigureCanvasPdf.print_pdf(self, filename, bbox_inches_restore, metadata)
   2806     file = filename._file
   2807 else:
-> 2808     file = PdfFile(filename, metadata=metadata)
   2809 try:
   2810     file.newPage(width, height)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/backends/backend_pdf.py:713, in PdfFile.__init__(self, filename, metadata)
    711 self.original_file_like = None
    712 self.tell_base = 0
--> 713 fh, opened = cbook.to_filehandle(filename, "wb", return_opened=True)
    714 if not opened:
    715     try:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/cbook/__init__.py:489, in to_filehandle(fname, flag, return_opened, encoding)
    487         fh = bz2.BZ2File(fname, flag)
    488     else:
--> 489         fh = open(fname, flag, encoding=encoding)
    490     opened = True
    491 elif hasattr(fname, 'seek'):

FileNotFoundError: [Errno 2] No such file or directory: 'figures/linear_iter_fig_1.pdf'
Error in callback <function _draw_all_if_interactive at 0x7f58bf0c5870> (for post_execute):
---------------------------------------------------------------------------
FileNotFoundError                         Traceback (most recent call last)
File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/texmanager.py:255, in TexManager._run_checked_subprocess(cls, command, tex, cwd)
    254 try:
--> 255     report = subprocess.check_output(
    256         command, cwd=cwd if cwd is not None else cls.texcache,
    257         stderr=subprocess.STDOUT)
    258 except FileNotFoundError as exc:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/subprocess.py:421, in check_output(timeout, *popenargs, **kwargs)
    419     kwargs['input'] = empty
--> 421 return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
    422            **kwargs).stdout

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/subprocess.py:503, in run(input, capture_output, timeout, check, *popenargs, **kwargs)
    501     kwargs['stderr'] = PIPE
--> 503 with Popen(*popenargs, **kwargs) as process:
    504     try:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/subprocess.py:971, in Popen.__init__(self, args, bufsize, executable, stdin, stdout, stderr, preexec_fn, close_fds, shell, cwd, env, universal_newlines, startupinfo, creationflags, restore_signals, start_new_session, pass_fds, user, group, extra_groups, encoding, errors, text, umask, pipesize)
    968             self.stderr = io.TextIOWrapper(self.stderr,
    969                     encoding=encoding, errors=errors)
--> 971     self._execute_child(args, executable, preexec_fn, close_fds,
    972                         pass_fds, cwd, env,
    973                         startupinfo, creationflags, shell,
    974                         p2cread, p2cwrite,
    975                         c2pread, c2pwrite,
    976                         errread, errwrite,
    977                         restore_signals,
    978                         gid, gids, uid, umask,
    979                         start_new_session)
    980 except:
    981     # Cleanup if the child failed starting.

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/subprocess.py:1863, in Popen._execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session)
   1862         err_msg = os.strerror(errno_num)
-> 1863     raise child_exception_type(errno_num, err_msg, err_filename)
   1864 raise child_exception_type(err_msg)

FileNotFoundError: [Errno 2] No such file or directory: 'latex'

The above exception was the direct cause of the following exception:

RuntimeError                              Traceback (most recent call last)
File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/pyplot.py:120, in _draw_all_if_interactive()
    118 def _draw_all_if_interactive():
    119     if matplotlib.is_interactive():
--> 120         draw_all()

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/_pylab_helpers.py:132, in Gcf.draw_all(cls, force)
    130 for manager in cls.get_all_fig_managers():
    131     if force or manager.canvas.figure.stale:
--> 132         manager.canvas.draw_idle()

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/backend_bases.py:2082, in FigureCanvasBase.draw_idle(self, *args, **kwargs)
   2080 if not self._is_idle_drawing:
   2081     with self._idle_draw_cntx():
-> 2082         self.draw(*args, **kwargs)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/backends/backend_agg.py:400, in FigureCanvasAgg.draw(self)
    396 # Acquire a lock on the shared font cache.
    397 with RendererAgg.lock, \
    398      (self.toolbar._wait_cursor_for_draw_cm() if self.toolbar
    399       else nullcontext()):
--> 400     self.figure.draw(self.renderer)
    401     # A GUI class may be need to update a window using this draw, so
    402     # don't forget to call the superclass.
    403     super().draw()

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/artist.py:95, in _finalize_rasterization.<locals>.draw_wrapper(artist, renderer, *args, **kwargs)
     93 @wraps(draw)
     94 def draw_wrapper(artist, renderer, *args, **kwargs):
---> 95     result = draw(artist, renderer, *args, **kwargs)
     96     if renderer._rasterizing:
     97         renderer.stop_rasterizing()

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/artist.py:72, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
     69     if artist.get_agg_filter() is not None:
     70         renderer.start_filter()
---> 72     return draw(artist, renderer)
     73 finally:
     74     if artist.get_agg_filter() is not None:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/figure.py:3140, in Figure.draw(self, renderer)
   3137         # ValueError can occur when resizing a window.
   3139 self.patch.draw(renderer)
-> 3140 mimage._draw_list_compositing_images(
   3141     renderer, self, artists, self.suppressComposite)
   3143 for sfig in self.subfigs:
   3144     sfig.draw(renderer)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/image.py:131, in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
    129 if not_composite or not has_images:
    130     for a in artists:
--> 131         a.draw(renderer)
    132 else:
    133     # Composite any adjacent images together
    134     image_group = []

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/artist.py:72, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
     69     if artist.get_agg_filter() is not None:
     70         renderer.start_filter()
---> 72     return draw(artist, renderer)
     73 finally:
     74     if artist.get_agg_filter() is not None:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/axes/_base.py:3064, in _AxesBase.draw(self, renderer)
   3061 if artists_rasterized:
   3062     _draw_rasterized(self.figure, artists_rasterized, renderer)
-> 3064 mimage._draw_list_compositing_images(
   3065     renderer, self, artists, self.figure.suppressComposite)
   3067 renderer.close_group('axes')
   3068 self.stale = False

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/image.py:131, in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
    129 if not_composite or not has_images:
    130     for a in artists:
--> 131         a.draw(renderer)
    132 else:
    133     # Composite any adjacent images together
    134     image_group = []

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/artist.py:72, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
     69     if artist.get_agg_filter() is not None:
     70         renderer.start_filter()
---> 72     return draw(artist, renderer)
     73 finally:
     74     if artist.get_agg_filter() is not None:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/axis.py:1377, in Axis.draw(self, renderer, *args, **kwargs)
   1374 renderer.open_group(__name__, gid=self.get_gid())
   1376 ticks_to_draw = self._update_ticks()
-> 1377 tlb1, tlb2 = self._get_ticklabel_bboxes(ticks_to_draw, renderer)
   1379 for tick in ticks_to_draw:
   1380     tick.draw(renderer)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/axis.py:1304, in Axis._get_ticklabel_bboxes(self, ticks, renderer)
   1302 if renderer is None:
   1303     renderer = self.figure._get_renderer()
-> 1304 return ([tick.label1.get_window_extent(renderer)
   1305          for tick in ticks if tick.label1.get_visible()],
   1306         [tick.label2.get_window_extent(renderer)
   1307          for tick in ticks if tick.label2.get_visible()])

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/axis.py:1304, in <listcomp>(.0)
   1302 if renderer is None:
   1303     renderer = self.figure._get_renderer()
-> 1304 return ([tick.label1.get_window_extent(renderer)
   1305          for tick in ticks if tick.label1.get_visible()],
   1306         [tick.label2.get_window_extent(renderer)
   1307          for tick in ticks if tick.label2.get_visible()])

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/text.py:959, in Text.get_window_extent(self, renderer, dpi)
    954     raise RuntimeError(
    955         "Cannot get window extent of text w/o renderer. You likely "
    956         "want to call 'figure.draw_without_rendering()' first.")
    958 with cbook._setattr_cm(self.figure, dpi=dpi):
--> 959     bbox, info, descent = self._get_layout(self._renderer)
    960     x, y = self.get_unitless_position()
    961     x, y = self.get_transform().transform((x, y))

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/text.py:378, in Text._get_layout(self, renderer)
    375 ys = []
    377 # Full vertical extent of font, including ascenders and descenders:
--> 378 _, lp_h, lp_d = _get_text_metrics_with_cache(
    379     renderer, "lp", self._fontproperties,
    380     ismath="TeX" if self.get_usetex() else False, dpi=self.figure.dpi)
    381 min_dy = (lp_h - lp_d) * self._linespacing
    383 for i, line in enumerate(lines):

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/text.py:97, in _get_text_metrics_with_cache(renderer, text, fontprop, ismath, dpi)
     94 """Call ``renderer.get_text_width_height_descent``, caching the results."""
     95 # Cached based on a copy of fontprop so that later in-place mutations of
     96 # the passed-in argument do not mess up the cache.
---> 97 return _get_text_metrics_with_cache_impl(
     98     weakref.ref(renderer), text, fontprop.copy(), ismath, dpi)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/text.py:105, in _get_text_metrics_with_cache_impl(renderer_ref, text, fontprop, ismath, dpi)
    101 @functools.lru_cache(4096)
    102 def _get_text_metrics_with_cache_impl(
    103         renderer_ref, text, fontprop, ismath, dpi):
    104     # dpi is unused, but participates in cache invalidation (via the renderer).
--> 105     return renderer_ref().get_text_width_height_descent(text, fontprop, ismath)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/backends/backend_agg.py:226, in RendererAgg.get_text_width_height_descent(self, s, prop, ismath)
    224 _api.check_in_list(["TeX", True, False], ismath=ismath)
    225 if ismath == "TeX":
--> 226     return super().get_text_width_height_descent(s, prop, ismath)
    228 if ismath:
    229     ox, oy, width, height, descent, font_image = \
    230         self.mathtext_parser.parse(s, self.dpi, prop)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/backend_bases.py:645, in RendererBase.get_text_width_height_descent(self, s, prop, ismath)
    641 fontsize = prop.get_size_in_points()
    643 if ismath == 'TeX':
    644     # todo: handle properties
--> 645     return self.get_texmanager().get_text_width_height_descent(
    646         s, fontsize, renderer=self)
    648 dpi = self.points_to_pixels(72)
    649 if ismath:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/texmanager.py:368, in TexManager.get_text_width_height_descent(cls, tex, fontsize, renderer)
    366 if tex.strip() == '':
    367     return 0, 0, 0
--> 368 dvifile = cls.make_dvi(tex, fontsize)
    369 dpi_fraction = renderer.points_to_pixels(1.) if renderer else 1
    370 with dviread.Dvi(dvifile, 72 * dpi_fraction) as dvi:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/texmanager.py:300, in TexManager.make_dvi(cls, tex, fontsize)
    298     with TemporaryDirectory(dir=cwd) as tmpdir:
    299         tmppath = Path(tmpdir)
--> 300         cls._run_checked_subprocess(
    301             ["latex", "-interaction=nonstopmode", "--halt-on-error",
    302              f"--output-directory={tmppath.name}",
    303              f"{texfile.name}"], tex, cwd=cwd)
    304         (tmppath / Path(dvifile).name).replace(dvifile)
    305 return dvifile

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/texmanager.py:259, in TexManager._run_checked_subprocess(cls, command, tex, cwd)
    255     report = subprocess.check_output(
    256         command, cwd=cwd if cwd is not None else cls.texcache,
    257         stderr=subprocess.STDOUT)
    258 except FileNotFoundError as exc:
--> 259     raise RuntimeError(
    260         'Failed to process string with tex because {} could not be '
    261         'found'.format(command[0])) from exc
    262 except subprocess.CalledProcessError as exc:
    263     raise RuntimeError(
    264         '{prog} was not able to process the following string:\n'
    265         '{tex!r}\n\n'
   (...)
    272             exc=exc.output.decode('utf-8', 'backslashreplace'))
    273         ) from None

RuntimeError: Failed to process string with tex because latex could not be found
---------------------------------------------------------------------------
FileNotFoundError                         Traceback (most recent call last)
File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/texmanager.py:255, in TexManager._run_checked_subprocess(cls, command, tex, cwd)
    254 try:
--> 255     report = subprocess.check_output(
    256         command, cwd=cwd if cwd is not None else cls.texcache,
    257         stderr=subprocess.STDOUT)
    258 except FileNotFoundError as exc:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/subprocess.py:421, in check_output(timeout, *popenargs, **kwargs)
    419     kwargs['input'] = empty
--> 421 return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
    422            **kwargs).stdout

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/subprocess.py:503, in run(input, capture_output, timeout, check, *popenargs, **kwargs)
    501     kwargs['stderr'] = PIPE
--> 503 with Popen(*popenargs, **kwargs) as process:
    504     try:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/subprocess.py:971, in Popen.__init__(self, args, bufsize, executable, stdin, stdout, stderr, preexec_fn, close_fds, shell, cwd, env, universal_newlines, startupinfo, creationflags, restore_signals, start_new_session, pass_fds, user, group, extra_groups, encoding, errors, text, umask, pipesize)
    968             self.stderr = io.TextIOWrapper(self.stderr,
    969                     encoding=encoding, errors=errors)
--> 971     self._execute_child(args, executable, preexec_fn, close_fds,
    972                         pass_fds, cwd, env,
    973                         startupinfo, creationflags, shell,
    974                         p2cread, p2cwrite,
    975                         c2pread, c2pwrite,
    976                         errread, errwrite,
    977                         restore_signals,
    978                         gid, gids, uid, umask,
    979                         start_new_session)
    980 except:
    981     # Cleanup if the child failed starting.

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/subprocess.py:1863, in Popen._execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session)
   1862         err_msg = os.strerror(errno_num)
-> 1863     raise child_exception_type(errno_num, err_msg, err_filename)
   1864 raise child_exception_type(err_msg)

FileNotFoundError: [Errno 2] No such file or directory: 'latex'

The above exception was the direct cause of the following exception:

RuntimeError                              Traceback (most recent call last)
File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/IPython/core/formatters.py:340, in BaseFormatter.__call__(self, obj)
    338     pass
    339 else:
--> 340     return printer(obj)
    341 # Finally look for special method names
    342 method = get_real_method(obj, self.print_method)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/IPython/core/pylabtools.py:152, in print_figure(fig, fmt, bbox_inches, base64, **kwargs)
    149     from matplotlib.backend_bases import FigureCanvasBase
    150     FigureCanvasBase(fig)
--> 152 fig.canvas.print_figure(bytes_io, **kw)
    153 data = bytes_io.getvalue()
    154 if fmt == 'svg':

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/backend_bases.py:2342, in FigureCanvasBase.print_figure(self, filename, dpi, facecolor, edgecolor, orientation, format, bbox_inches, pad_inches, bbox_extra_artists, backend, **kwargs)
   2336     renderer = _get_renderer(
   2337         self.figure,
   2338         functools.partial(
   2339             print_method, orientation=orientation)
   2340     )
   2341     with getattr(renderer, "_draw_disabled", nullcontext)():
-> 2342         self.figure.draw(renderer)
   2344 if bbox_inches:
   2345     if bbox_inches == "tight":

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/artist.py:95, in _finalize_rasterization.<locals>.draw_wrapper(artist, renderer, *args, **kwargs)
     93 @wraps(draw)
     94 def draw_wrapper(artist, renderer, *args, **kwargs):
---> 95     result = draw(artist, renderer, *args, **kwargs)
     96     if renderer._rasterizing:
     97         renderer.stop_rasterizing()

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/artist.py:72, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
     69     if artist.get_agg_filter() is not None:
     70         renderer.start_filter()
---> 72     return draw(artist, renderer)
     73 finally:
     74     if artist.get_agg_filter() is not None:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/figure.py:3140, in Figure.draw(self, renderer)
   3137         # ValueError can occur when resizing a window.
   3139 self.patch.draw(renderer)
-> 3140 mimage._draw_list_compositing_images(
   3141     renderer, self, artists, self.suppressComposite)
   3143 for sfig in self.subfigs:
   3144     sfig.draw(renderer)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/image.py:131, in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
    129 if not_composite or not has_images:
    130     for a in artists:
--> 131         a.draw(renderer)
    132 else:
    133     # Composite any adjacent images together
    134     image_group = []

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/artist.py:72, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
     69     if artist.get_agg_filter() is not None:
     70         renderer.start_filter()
---> 72     return draw(artist, renderer)
     73 finally:
     74     if artist.get_agg_filter() is not None:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/axes/_base.py:3064, in _AxesBase.draw(self, renderer)
   3061 if artists_rasterized:
   3062     _draw_rasterized(self.figure, artists_rasterized, renderer)
-> 3064 mimage._draw_list_compositing_images(
   3065     renderer, self, artists, self.figure.suppressComposite)
   3067 renderer.close_group('axes')
   3068 self.stale = False

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/image.py:131, in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
    129 if not_composite or not has_images:
    130     for a in artists:
--> 131         a.draw(renderer)
    132 else:
    133     # Composite any adjacent images together
    134     image_group = []

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/artist.py:72, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
     69     if artist.get_agg_filter() is not None:
     70         renderer.start_filter()
---> 72     return draw(artist, renderer)
     73 finally:
     74     if artist.get_agg_filter() is not None:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/axis.py:1377, in Axis.draw(self, renderer, *args, **kwargs)
   1374 renderer.open_group(__name__, gid=self.get_gid())
   1376 ticks_to_draw = self._update_ticks()
-> 1377 tlb1, tlb2 = self._get_ticklabel_bboxes(ticks_to_draw, renderer)
   1379 for tick in ticks_to_draw:
   1380     tick.draw(renderer)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/axis.py:1304, in Axis._get_ticklabel_bboxes(self, ticks, renderer)
   1302 if renderer is None:
   1303     renderer = self.figure._get_renderer()
-> 1304 return ([tick.label1.get_window_extent(renderer)
   1305          for tick in ticks if tick.label1.get_visible()],
   1306         [tick.label2.get_window_extent(renderer)
   1307          for tick in ticks if tick.label2.get_visible()])

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/axis.py:1304, in <listcomp>(.0)
   1302 if renderer is None:
   1303     renderer = self.figure._get_renderer()
-> 1304 return ([tick.label1.get_window_extent(renderer)
   1305          for tick in ticks if tick.label1.get_visible()],
   1306         [tick.label2.get_window_extent(renderer)
   1307          for tick in ticks if tick.label2.get_visible()])

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/text.py:959, in Text.get_window_extent(self, renderer, dpi)
    954     raise RuntimeError(
    955         "Cannot get window extent of text w/o renderer. You likely "
    956         "want to call 'figure.draw_without_rendering()' first.")
    958 with cbook._setattr_cm(self.figure, dpi=dpi):
--> 959     bbox, info, descent = self._get_layout(self._renderer)
    960     x, y = self.get_unitless_position()
    961     x, y = self.get_transform().transform((x, y))

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/text.py:378, in Text._get_layout(self, renderer)
    375 ys = []
    377 # Full vertical extent of font, including ascenders and descenders:
--> 378 _, lp_h, lp_d = _get_text_metrics_with_cache(
    379     renderer, "lp", self._fontproperties,
    380     ismath="TeX" if self.get_usetex() else False, dpi=self.figure.dpi)
    381 min_dy = (lp_h - lp_d) * self._linespacing
    383 for i, line in enumerate(lines):

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/text.py:97, in _get_text_metrics_with_cache(renderer, text, fontprop, ismath, dpi)
     94 """Call ``renderer.get_text_width_height_descent``, caching the results."""
     95 # Cached based on a copy of fontprop so that later in-place mutations of
     96 # the passed-in argument do not mess up the cache.
---> 97 return _get_text_metrics_with_cache_impl(
     98     weakref.ref(renderer), text, fontprop.copy(), ismath, dpi)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/text.py:105, in _get_text_metrics_with_cache_impl(renderer_ref, text, fontprop, ismath, dpi)
    101 @functools.lru_cache(4096)
    102 def _get_text_metrics_with_cache_impl(
    103         renderer_ref, text, fontprop, ismath, dpi):
    104     # dpi is unused, but participates in cache invalidation (via the renderer).
--> 105     return renderer_ref().get_text_width_height_descent(text, fontprop, ismath)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/backends/backend_agg.py:226, in RendererAgg.get_text_width_height_descent(self, s, prop, ismath)
    224 _api.check_in_list(["TeX", True, False], ismath=ismath)
    225 if ismath == "TeX":
--> 226     return super().get_text_width_height_descent(s, prop, ismath)
    228 if ismath:
    229     ox, oy, width, height, descent, font_image = \
    230         self.mathtext_parser.parse(s, self.dpi, prop)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/backend_bases.py:645, in RendererBase.get_text_width_height_descent(self, s, prop, ismath)
    641 fontsize = prop.get_size_in_points()
    643 if ismath == 'TeX':
    644     # todo: handle properties
--> 645     return self.get_texmanager().get_text_width_height_descent(
    646         s, fontsize, renderer=self)
    648 dpi = self.points_to_pixels(72)
    649 if ismath:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/texmanager.py:368, in TexManager.get_text_width_height_descent(cls, tex, fontsize, renderer)
    366 if tex.strip() == '':
    367     return 0, 0, 0
--> 368 dvifile = cls.make_dvi(tex, fontsize)
    369 dpi_fraction = renderer.points_to_pixels(1.) if renderer else 1
    370 with dviread.Dvi(dvifile, 72 * dpi_fraction) as dvi:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/texmanager.py:300, in TexManager.make_dvi(cls, tex, fontsize)
    298     with TemporaryDirectory(dir=cwd) as tmpdir:
    299         tmppath = Path(tmpdir)
--> 300         cls._run_checked_subprocess(
    301             ["latex", "-interaction=nonstopmode", "--halt-on-error",
    302              f"--output-directory={tmppath.name}",
    303              f"{texfile.name}"], tex, cwd=cwd)
    304         (tmppath / Path(dvifile).name).replace(dvifile)
    305 return dvifile

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/texmanager.py:259, in TexManager._run_checked_subprocess(cls, command, tex, cwd)
    255     report = subprocess.check_output(
    256         command, cwd=cwd if cwd is not None else cls.texcache,
    257         stderr=subprocess.STDOUT)
    258 except FileNotFoundError as exc:
--> 259     raise RuntimeError(
    260         'Failed to process string with tex because {} could not be '
    261         'found'.format(command[0])) from exc
    262 except subprocess.CalledProcessError as exc:
    263     raise RuntimeError(
    264         '{prog} was not able to process the following string:\n'
    265         '{tex!r}\n\n'
   (...)
    272             exc=exc.output.decode('utf-8', 'backslashreplace'))
    273         ) from None

RuntimeError: Failed to process string with tex because latex could not be found
<Figure size 640x480 with 1 Axes>

iid_job_search.py#

Hide code cell source
"""
VFI approach to job search in the infinite-horizon IID case.

"""

from quantecon import compute_fixed_point

from two_period_job_search import create_job_search_model

from numba import njit
import numpy as np


# A model with default parameters
default_model = create_job_search_model()


@njit
def T(v, model):
    """ The Bellman operator. """
    n, w_vals, φ, β, c = model
    return np.array([np.maximum(w / (1 - β),
                    c + β * np.sum(v * φ)) for w in w_vals])


@njit
def get_greedy(v, model):
    """ Get a v-greedy policy. """
    n, w_vals, φ, β, c = model
    σ = w_vals / (1 - β) >= c + β * np.sum(v * φ)  # Boolean policy vector
    return σ


def vfi(model=default_model):
    """ Solve the infinite-horizon IID job search model by VFI. """
    v_init = np.zeros_like(model.w_vals)
    v_star = compute_fixed_point(lambda v: T(v, model), v_init,
                                 error_tol=1e-5, max_iter=1000, print_skip=25)
    σ_star = get_greedy(v_star, model)
    return v_star, σ_star



# == Plots == #

import matplotlib.pyplot as plt
import matplotlib.pyplot as plt

plt.rcParams.update({"text.usetex": True, "font.size": 14})


def fig_vseq(model=default_model,
                k=3,
                savefig=False,
                figname="figures/iid_job_search_1.pdf",
                fs=10):

    v = np.zeros_like(model.w_vals)
    fig, ax = plt.subplots(figsize=(9, 5.5))
    for i in range(k):
        ax.plot(model.w_vals, v, linewidth=3, alpha=0.6,
                label=f"iterate {i}")
        v = T(v, model)

    for i in range(1000):
        v = T(v, model)

    ax.plot(model.w_vals, v, "k-", linewidth=3.0,
            label="iterate 1000", alpha=0.7)

    fontdict = {'fontsize': fs}
    ax.set_xlabel("wage offer", fontdict=fontdict)
    ax.set_ylabel("lifetime value", fontdict=fontdict)

    ax.legend(fontsize=fs, frameon=False)

    if savefig:
        fig.savefig(figname)


def fig_vstar(model=default_model,
              savefig=False, fs=10,
              figname="figures/iid_job_search_3.pdf"):
    """ Plot the fixed point. """
    n, w_vals, φ, β, c = model
    v_star, σ_star = vfi(model)

    fig, ax = plt.subplots(figsize=(9, 5.5))
    ax.plot(w_vals, v_star, "k-", linewidth=1.5, label="value function")
    cont_val = c + β * np.sum(v_star * φ)
    ax.plot(w_vals, [cont_val]*(n+1),
            "--",
            linewidth=5,
            alpha=0.5,
            label="continuation value")

    ax.plot(w_vals,
            w_vals / (1 - β),
            "--",
            linewidth=5,
            alpha=0.5,
            label=r"$w/(1 - \beta)$")

    ax.legend(frameon=False, fontsize=fs, loc="lower right")

    if savefig:
        fig.savefig(figname)
fig_vseq()
Error in callback <function _draw_all_if_interactive at 0x7f58bf0c5870> (for post_execute):
---------------------------------------------------------------------------
FileNotFoundError                         Traceback (most recent call last)
File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/texmanager.py:255, in TexManager._run_checked_subprocess(cls, command, tex, cwd)
    254 try:
--> 255     report = subprocess.check_output(
    256         command, cwd=cwd if cwd is not None else cls.texcache,
    257         stderr=subprocess.STDOUT)
    258 except FileNotFoundError as exc:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/subprocess.py:421, in check_output(timeout, *popenargs, **kwargs)
    419     kwargs['input'] = empty
--> 421 return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
    422            **kwargs).stdout

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/subprocess.py:503, in run(input, capture_output, timeout, check, *popenargs, **kwargs)
    501     kwargs['stderr'] = PIPE
--> 503 with Popen(*popenargs, **kwargs) as process:
    504     try:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/subprocess.py:971, in Popen.__init__(self, args, bufsize, executable, stdin, stdout, stderr, preexec_fn, close_fds, shell, cwd, env, universal_newlines, startupinfo, creationflags, restore_signals, start_new_session, pass_fds, user, group, extra_groups, encoding, errors, text, umask, pipesize)
    968             self.stderr = io.TextIOWrapper(self.stderr,
    969                     encoding=encoding, errors=errors)
--> 971     self._execute_child(args, executable, preexec_fn, close_fds,
    972                         pass_fds, cwd, env,
    973                         startupinfo, creationflags, shell,
    974                         p2cread, p2cwrite,
    975                         c2pread, c2pwrite,
    976                         errread, errwrite,
    977                         restore_signals,
    978                         gid, gids, uid, umask,
    979                         start_new_session)
    980 except:
    981     # Cleanup if the child failed starting.

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/subprocess.py:1863, in Popen._execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session)
   1862         err_msg = os.strerror(errno_num)
-> 1863     raise child_exception_type(errno_num, err_msg, err_filename)
   1864 raise child_exception_type(err_msg)

FileNotFoundError: [Errno 2] No such file or directory: 'latex'

The above exception was the direct cause of the following exception:

RuntimeError                              Traceback (most recent call last)
File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/pyplot.py:120, in _draw_all_if_interactive()
    118 def _draw_all_if_interactive():
    119     if matplotlib.is_interactive():
--> 120         draw_all()

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/_pylab_helpers.py:132, in Gcf.draw_all(cls, force)
    130 for manager in cls.get_all_fig_managers():
    131     if force or manager.canvas.figure.stale:
--> 132         manager.canvas.draw_idle()

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/backend_bases.py:2082, in FigureCanvasBase.draw_idle(self, *args, **kwargs)
   2080 if not self._is_idle_drawing:
   2081     with self._idle_draw_cntx():
-> 2082         self.draw(*args, **kwargs)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/backends/backend_agg.py:400, in FigureCanvasAgg.draw(self)
    396 # Acquire a lock on the shared font cache.
    397 with RendererAgg.lock, \
    398      (self.toolbar._wait_cursor_for_draw_cm() if self.toolbar
    399       else nullcontext()):
--> 400     self.figure.draw(self.renderer)
    401     # A GUI class may be need to update a window using this draw, so
    402     # don't forget to call the superclass.
    403     super().draw()

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/artist.py:95, in _finalize_rasterization.<locals>.draw_wrapper(artist, renderer, *args, **kwargs)
     93 @wraps(draw)
     94 def draw_wrapper(artist, renderer, *args, **kwargs):
---> 95     result = draw(artist, renderer, *args, **kwargs)
     96     if renderer._rasterizing:
     97         renderer.stop_rasterizing()

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/artist.py:72, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
     69     if artist.get_agg_filter() is not None:
     70         renderer.start_filter()
---> 72     return draw(artist, renderer)
     73 finally:
     74     if artist.get_agg_filter() is not None:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/figure.py:3140, in Figure.draw(self, renderer)
   3137         # ValueError can occur when resizing a window.
   3139 self.patch.draw(renderer)
-> 3140 mimage._draw_list_compositing_images(
   3141     renderer, self, artists, self.suppressComposite)
   3143 for sfig in self.subfigs:
   3144     sfig.draw(renderer)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/image.py:131, in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
    129 if not_composite or not has_images:
    130     for a in artists:
--> 131         a.draw(renderer)
    132 else:
    133     # Composite any adjacent images together
    134     image_group = []

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/artist.py:72, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
     69     if artist.get_agg_filter() is not None:
     70         renderer.start_filter()
---> 72     return draw(artist, renderer)
     73 finally:
     74     if artist.get_agg_filter() is not None:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/axes/_base.py:3064, in _AxesBase.draw(self, renderer)
   3061 if artists_rasterized:
   3062     _draw_rasterized(self.figure, artists_rasterized, renderer)
-> 3064 mimage._draw_list_compositing_images(
   3065     renderer, self, artists, self.figure.suppressComposite)
   3067 renderer.close_group('axes')
   3068 self.stale = False

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/image.py:131, in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
    129 if not_composite or not has_images:
    130     for a in artists:
--> 131         a.draw(renderer)
    132 else:
    133     # Composite any adjacent images together
    134     image_group = []

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/artist.py:72, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
     69     if artist.get_agg_filter() is not None:
     70         renderer.start_filter()
---> 72     return draw(artist, renderer)
     73 finally:
     74     if artist.get_agg_filter() is not None:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/axis.py:1377, in Axis.draw(self, renderer, *args, **kwargs)
   1374 renderer.open_group(__name__, gid=self.get_gid())
   1376 ticks_to_draw = self._update_ticks()
-> 1377 tlb1, tlb2 = self._get_ticklabel_bboxes(ticks_to_draw, renderer)
   1379 for tick in ticks_to_draw:
   1380     tick.draw(renderer)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/axis.py:1304, in Axis._get_ticklabel_bboxes(self, ticks, renderer)
   1302 if renderer is None:
   1303     renderer = self.figure._get_renderer()
-> 1304 return ([tick.label1.get_window_extent(renderer)
   1305          for tick in ticks if tick.label1.get_visible()],
   1306         [tick.label2.get_window_extent(renderer)
   1307          for tick in ticks if tick.label2.get_visible()])

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/axis.py:1304, in <listcomp>(.0)
   1302 if renderer is None:
   1303     renderer = self.figure._get_renderer()
-> 1304 return ([tick.label1.get_window_extent(renderer)
   1305          for tick in ticks if tick.label1.get_visible()],
   1306         [tick.label2.get_window_extent(renderer)
   1307          for tick in ticks if tick.label2.get_visible()])

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/text.py:959, in Text.get_window_extent(self, renderer, dpi)
    954     raise RuntimeError(
    955         "Cannot get window extent of text w/o renderer. You likely "
    956         "want to call 'figure.draw_without_rendering()' first.")
    958 with cbook._setattr_cm(self.figure, dpi=dpi):
--> 959     bbox, info, descent = self._get_layout(self._renderer)
    960     x, y = self.get_unitless_position()
    961     x, y = self.get_transform().transform((x, y))

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/text.py:378, in Text._get_layout(self, renderer)
    375 ys = []
    377 # Full vertical extent of font, including ascenders and descenders:
--> 378 _, lp_h, lp_d = _get_text_metrics_with_cache(
    379     renderer, "lp", self._fontproperties,
    380     ismath="TeX" if self.get_usetex() else False, dpi=self.figure.dpi)
    381 min_dy = (lp_h - lp_d) * self._linespacing
    383 for i, line in enumerate(lines):

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/text.py:97, in _get_text_metrics_with_cache(renderer, text, fontprop, ismath, dpi)
     94 """Call ``renderer.get_text_width_height_descent``, caching the results."""
     95 # Cached based on a copy of fontprop so that later in-place mutations of
     96 # the passed-in argument do not mess up the cache.
---> 97 return _get_text_metrics_with_cache_impl(
     98     weakref.ref(renderer), text, fontprop.copy(), ismath, dpi)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/text.py:105, in _get_text_metrics_with_cache_impl(renderer_ref, text, fontprop, ismath, dpi)
    101 @functools.lru_cache(4096)
    102 def _get_text_metrics_with_cache_impl(
    103         renderer_ref, text, fontprop, ismath, dpi):
    104     # dpi is unused, but participates in cache invalidation (via the renderer).
--> 105     return renderer_ref().get_text_width_height_descent(text, fontprop, ismath)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/backends/backend_agg.py:226, in RendererAgg.get_text_width_height_descent(self, s, prop, ismath)
    224 _api.check_in_list(["TeX", True, False], ismath=ismath)
    225 if ismath == "TeX":
--> 226     return super().get_text_width_height_descent(s, prop, ismath)
    228 if ismath:
    229     ox, oy, width, height, descent, font_image = \
    230         self.mathtext_parser.parse(s, self.dpi, prop)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/backend_bases.py:645, in RendererBase.get_text_width_height_descent(self, s, prop, ismath)
    641 fontsize = prop.get_size_in_points()
    643 if ismath == 'TeX':
    644     # todo: handle properties
--> 645     return self.get_texmanager().get_text_width_height_descent(
    646         s, fontsize, renderer=self)
    648 dpi = self.points_to_pixels(72)
    649 if ismath:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/texmanager.py:368, in TexManager.get_text_width_height_descent(cls, tex, fontsize, renderer)
    366 if tex.strip() == '':
    367     return 0, 0, 0
--> 368 dvifile = cls.make_dvi(tex, fontsize)
    369 dpi_fraction = renderer.points_to_pixels(1.) if renderer else 1
    370 with dviread.Dvi(dvifile, 72 * dpi_fraction) as dvi:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/texmanager.py:300, in TexManager.make_dvi(cls, tex, fontsize)
    298     with TemporaryDirectory(dir=cwd) as tmpdir:
    299         tmppath = Path(tmpdir)
--> 300         cls._run_checked_subprocess(
    301             ["latex", "-interaction=nonstopmode", "--halt-on-error",
    302              f"--output-directory={tmppath.name}",
    303              f"{texfile.name}"], tex, cwd=cwd)
    304         (tmppath / Path(dvifile).name).replace(dvifile)
    305 return dvifile

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/texmanager.py:259, in TexManager._run_checked_subprocess(cls, command, tex, cwd)
    255     report = subprocess.check_output(
    256         command, cwd=cwd if cwd is not None else cls.texcache,
    257         stderr=subprocess.STDOUT)
    258 except FileNotFoundError as exc:
--> 259     raise RuntimeError(
    260         'Failed to process string with tex because {} could not be '
    261         'found'.format(command[0])) from exc
    262 except subprocess.CalledProcessError as exc:
    263     raise RuntimeError(
    264         '{prog} was not able to process the following string:\n'
    265         '{tex!r}\n\n'
   (...)
    272             exc=exc.output.decode('utf-8', 'backslashreplace'))
    273         ) from None

RuntimeError: Failed to process string with tex because latex could not be found
---------------------------------------------------------------------------
FileNotFoundError                         Traceback (most recent call last)
File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/texmanager.py:255, in TexManager._run_checked_subprocess(cls, command, tex, cwd)
    254 try:
--> 255     report = subprocess.check_output(
    256         command, cwd=cwd if cwd is not None else cls.texcache,
    257         stderr=subprocess.STDOUT)
    258 except FileNotFoundError as exc:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/subprocess.py:421, in check_output(timeout, *popenargs, **kwargs)
    419     kwargs['input'] = empty
--> 421 return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
    422            **kwargs).stdout

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/subprocess.py:503, in run(input, capture_output, timeout, check, *popenargs, **kwargs)
    501     kwargs['stderr'] = PIPE
--> 503 with Popen(*popenargs, **kwargs) as process:
    504     try:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/subprocess.py:971, in Popen.__init__(self, args, bufsize, executable, stdin, stdout, stderr, preexec_fn, close_fds, shell, cwd, env, universal_newlines, startupinfo, creationflags, restore_signals, start_new_session, pass_fds, user, group, extra_groups, encoding, errors, text, umask, pipesize)
    968             self.stderr = io.TextIOWrapper(self.stderr,
    969                     encoding=encoding, errors=errors)
--> 971     self._execute_child(args, executable, preexec_fn, close_fds,
    972                         pass_fds, cwd, env,
    973                         startupinfo, creationflags, shell,
    974                         p2cread, p2cwrite,
    975                         c2pread, c2pwrite,
    976                         errread, errwrite,
    977                         restore_signals,
    978                         gid, gids, uid, umask,
    979                         start_new_session)
    980 except:
    981     # Cleanup if the child failed starting.

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/subprocess.py:1863, in Popen._execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session)
   1862         err_msg = os.strerror(errno_num)
-> 1863     raise child_exception_type(errno_num, err_msg, err_filename)
   1864 raise child_exception_type(err_msg)

FileNotFoundError: [Errno 2] No such file or directory: 'latex'

The above exception was the direct cause of the following exception:

RuntimeError                              Traceback (most recent call last)
File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/IPython/core/formatters.py:340, in BaseFormatter.__call__(self, obj)
    338     pass
    339 else:
--> 340     return printer(obj)
    341 # Finally look for special method names
    342 method = get_real_method(obj, self.print_method)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/IPython/core/pylabtools.py:152, in print_figure(fig, fmt, bbox_inches, base64, **kwargs)
    149     from matplotlib.backend_bases import FigureCanvasBase
    150     FigureCanvasBase(fig)
--> 152 fig.canvas.print_figure(bytes_io, **kw)
    153 data = bytes_io.getvalue()
    154 if fmt == 'svg':

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/backend_bases.py:2342, in FigureCanvasBase.print_figure(self, filename, dpi, facecolor, edgecolor, orientation, format, bbox_inches, pad_inches, bbox_extra_artists, backend, **kwargs)
   2336     renderer = _get_renderer(
   2337         self.figure,
   2338         functools.partial(
   2339             print_method, orientation=orientation)
   2340     )
   2341     with getattr(renderer, "_draw_disabled", nullcontext)():
-> 2342         self.figure.draw(renderer)
   2344 if bbox_inches:
   2345     if bbox_inches == "tight":

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/artist.py:95, in _finalize_rasterization.<locals>.draw_wrapper(artist, renderer, *args, **kwargs)
     93 @wraps(draw)
     94 def draw_wrapper(artist, renderer, *args, **kwargs):
---> 95     result = draw(artist, renderer, *args, **kwargs)
     96     if renderer._rasterizing:
     97         renderer.stop_rasterizing()

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/artist.py:72, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
     69     if artist.get_agg_filter() is not None:
     70         renderer.start_filter()
---> 72     return draw(artist, renderer)
     73 finally:
     74     if artist.get_agg_filter() is not None:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/figure.py:3140, in Figure.draw(self, renderer)
   3137         # ValueError can occur when resizing a window.
   3139 self.patch.draw(renderer)
-> 3140 mimage._draw_list_compositing_images(
   3141     renderer, self, artists, self.suppressComposite)
   3143 for sfig in self.subfigs:
   3144     sfig.draw(renderer)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/image.py:131, in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
    129 if not_composite or not has_images:
    130     for a in artists:
--> 131         a.draw(renderer)
    132 else:
    133     # Composite any adjacent images together
    134     image_group = []

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/artist.py:72, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
     69     if artist.get_agg_filter() is not None:
     70         renderer.start_filter()
---> 72     return draw(artist, renderer)
     73 finally:
     74     if artist.get_agg_filter() is not None:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/axes/_base.py:3064, in _AxesBase.draw(self, renderer)
   3061 if artists_rasterized:
   3062     _draw_rasterized(self.figure, artists_rasterized, renderer)
-> 3064 mimage._draw_list_compositing_images(
   3065     renderer, self, artists, self.figure.suppressComposite)
   3067 renderer.close_group('axes')
   3068 self.stale = False

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/image.py:131, in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
    129 if not_composite or not has_images:
    130     for a in artists:
--> 131         a.draw(renderer)
    132 else:
    133     # Composite any adjacent images together
    134     image_group = []

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/artist.py:72, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
     69     if artist.get_agg_filter() is not None:
     70         renderer.start_filter()
---> 72     return draw(artist, renderer)
     73 finally:
     74     if artist.get_agg_filter() is not None:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/axis.py:1377, in Axis.draw(self, renderer, *args, **kwargs)
   1374 renderer.open_group(__name__, gid=self.get_gid())
   1376 ticks_to_draw = self._update_ticks()
-> 1377 tlb1, tlb2 = self._get_ticklabel_bboxes(ticks_to_draw, renderer)
   1379 for tick in ticks_to_draw:
   1380     tick.draw(renderer)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/axis.py:1304, in Axis._get_ticklabel_bboxes(self, ticks, renderer)
   1302 if renderer is None:
   1303     renderer = self.figure._get_renderer()
-> 1304 return ([tick.label1.get_window_extent(renderer)
   1305          for tick in ticks if tick.label1.get_visible()],
   1306         [tick.label2.get_window_extent(renderer)
   1307          for tick in ticks if tick.label2.get_visible()])

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/axis.py:1304, in <listcomp>(.0)
   1302 if renderer is None:
   1303     renderer = self.figure._get_renderer()
-> 1304 return ([tick.label1.get_window_extent(renderer)
   1305          for tick in ticks if tick.label1.get_visible()],
   1306         [tick.label2.get_window_extent(renderer)
   1307          for tick in ticks if tick.label2.get_visible()])

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/text.py:959, in Text.get_window_extent(self, renderer, dpi)
    954     raise RuntimeError(
    955         "Cannot get window extent of text w/o renderer. You likely "
    956         "want to call 'figure.draw_without_rendering()' first.")
    958 with cbook._setattr_cm(self.figure, dpi=dpi):
--> 959     bbox, info, descent = self._get_layout(self._renderer)
    960     x, y = self.get_unitless_position()
    961     x, y = self.get_transform().transform((x, y))

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/text.py:378, in Text._get_layout(self, renderer)
    375 ys = []
    377 # Full vertical extent of font, including ascenders and descenders:
--> 378 _, lp_h, lp_d = _get_text_metrics_with_cache(
    379     renderer, "lp", self._fontproperties,
    380     ismath="TeX" if self.get_usetex() else False, dpi=self.figure.dpi)
    381 min_dy = (lp_h - lp_d) * self._linespacing
    383 for i, line in enumerate(lines):

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/text.py:97, in _get_text_metrics_with_cache(renderer, text, fontprop, ismath, dpi)
     94 """Call ``renderer.get_text_width_height_descent``, caching the results."""
     95 # Cached based on a copy of fontprop so that later in-place mutations of
     96 # the passed-in argument do not mess up the cache.
---> 97 return _get_text_metrics_with_cache_impl(
     98     weakref.ref(renderer), text, fontprop.copy(), ismath, dpi)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/text.py:105, in _get_text_metrics_with_cache_impl(renderer_ref, text, fontprop, ismath, dpi)
    101 @functools.lru_cache(4096)
    102 def _get_text_metrics_with_cache_impl(
    103         renderer_ref, text, fontprop, ismath, dpi):
    104     # dpi is unused, but participates in cache invalidation (via the renderer).
--> 105     return renderer_ref().get_text_width_height_descent(text, fontprop, ismath)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/backends/backend_agg.py:226, in RendererAgg.get_text_width_height_descent(self, s, prop, ismath)
    224 _api.check_in_list(["TeX", True, False], ismath=ismath)
    225 if ismath == "TeX":
--> 226     return super().get_text_width_height_descent(s, prop, ismath)
    228 if ismath:
    229     ox, oy, width, height, descent, font_image = \
    230         self.mathtext_parser.parse(s, self.dpi, prop)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/backend_bases.py:645, in RendererBase.get_text_width_height_descent(self, s, prop, ismath)
    641 fontsize = prop.get_size_in_points()
    643 if ismath == 'TeX':
    644     # todo: handle properties
--> 645     return self.get_texmanager().get_text_width_height_descent(
    646         s, fontsize, renderer=self)
    648 dpi = self.points_to_pixels(72)
    649 if ismath:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/texmanager.py:368, in TexManager.get_text_width_height_descent(cls, tex, fontsize, renderer)
    366 if tex.strip() == '':
    367     return 0, 0, 0
--> 368 dvifile = cls.make_dvi(tex, fontsize)
    369 dpi_fraction = renderer.points_to_pixels(1.) if renderer else 1
    370 with dviread.Dvi(dvifile, 72 * dpi_fraction) as dvi:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/texmanager.py:300, in TexManager.make_dvi(cls, tex, fontsize)
    298     with TemporaryDirectory(dir=cwd) as tmpdir:
    299         tmppath = Path(tmpdir)
--> 300         cls._run_checked_subprocess(
    301             ["latex", "-interaction=nonstopmode", "--halt-on-error",
    302              f"--output-directory={tmppath.name}",
    303              f"{texfile.name}"], tex, cwd=cwd)
    304         (tmppath / Path(dvifile).name).replace(dvifile)
    305 return dvifile

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/texmanager.py:259, in TexManager._run_checked_subprocess(cls, command, tex, cwd)
    255     report = subprocess.check_output(
    256         command, cwd=cwd if cwd is not None else cls.texcache,
    257         stderr=subprocess.STDOUT)
    258 except FileNotFoundError as exc:
--> 259     raise RuntimeError(
    260         'Failed to process string with tex because {} could not be '
    261         'found'.format(command[0])) from exc
    262 except subprocess.CalledProcessError as exc:
    263     raise RuntimeError(
    264         '{prog} was not able to process the following string:\n'
    265         '{tex!r}\n\n'
   (...)
    272             exc=exc.output.decode('utf-8', 'backslashreplace'))
    273         ) from None

RuntimeError: Failed to process string with tex because latex could not be found
<Figure size 900x550 with 1 Axes>
fig_vstar()
Iteration    Distance       Elapsed (seconds)
---------------------------------------------
23           9.192e-06      3.846e-03         
Converged in 23 steps
Error in callback <function _draw_all_if_interactive at 0x7f58bf0c5870> (for post_execute):
---------------------------------------------------------------------------
FileNotFoundError                         Traceback (most recent call last)
File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/texmanager.py:255, in TexManager._run_checked_subprocess(cls, command, tex, cwd)
    254 try:
--> 255     report = subprocess.check_output(
    256         command, cwd=cwd if cwd is not None else cls.texcache,
    257         stderr=subprocess.STDOUT)
    258 except FileNotFoundError as exc:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/subprocess.py:421, in check_output(timeout, *popenargs, **kwargs)
    419     kwargs['input'] = empty
--> 421 return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
    422            **kwargs).stdout

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/subprocess.py:503, in run(input, capture_output, timeout, check, *popenargs, **kwargs)
    501     kwargs['stderr'] = PIPE
--> 503 with Popen(*popenargs, **kwargs) as process:
    504     try:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/subprocess.py:971, in Popen.__init__(self, args, bufsize, executable, stdin, stdout, stderr, preexec_fn, close_fds, shell, cwd, env, universal_newlines, startupinfo, creationflags, restore_signals, start_new_session, pass_fds, user, group, extra_groups, encoding, errors, text, umask, pipesize)
    968             self.stderr = io.TextIOWrapper(self.stderr,
    969                     encoding=encoding, errors=errors)
--> 971     self._execute_child(args, executable, preexec_fn, close_fds,
    972                         pass_fds, cwd, env,
    973                         startupinfo, creationflags, shell,
    974                         p2cread, p2cwrite,
    975                         c2pread, c2pwrite,
    976                         errread, errwrite,
    977                         restore_signals,
    978                         gid, gids, uid, umask,
    979                         start_new_session)
    980 except:
    981     # Cleanup if the child failed starting.

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/subprocess.py:1863, in Popen._execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session)
   1862         err_msg = os.strerror(errno_num)
-> 1863     raise child_exception_type(errno_num, err_msg, err_filename)
   1864 raise child_exception_type(err_msg)

FileNotFoundError: [Errno 2] No such file or directory: 'latex'

The above exception was the direct cause of the following exception:

RuntimeError                              Traceback (most recent call last)
File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/pyplot.py:120, in _draw_all_if_interactive()
    118 def _draw_all_if_interactive():
    119     if matplotlib.is_interactive():
--> 120         draw_all()

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/_pylab_helpers.py:132, in Gcf.draw_all(cls, force)
    130 for manager in cls.get_all_fig_managers():
    131     if force or manager.canvas.figure.stale:
--> 132         manager.canvas.draw_idle()

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/backend_bases.py:2082, in FigureCanvasBase.draw_idle(self, *args, **kwargs)
   2080 if not self._is_idle_drawing:
   2081     with self._idle_draw_cntx():
-> 2082         self.draw(*args, **kwargs)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/backends/backend_agg.py:400, in FigureCanvasAgg.draw(self)
    396 # Acquire a lock on the shared font cache.
    397 with RendererAgg.lock, \
    398      (self.toolbar._wait_cursor_for_draw_cm() if self.toolbar
    399       else nullcontext()):
--> 400     self.figure.draw(self.renderer)
    401     # A GUI class may be need to update a window using this draw, so
    402     # don't forget to call the superclass.
    403     super().draw()

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/artist.py:95, in _finalize_rasterization.<locals>.draw_wrapper(artist, renderer, *args, **kwargs)
     93 @wraps(draw)
     94 def draw_wrapper(artist, renderer, *args, **kwargs):
---> 95     result = draw(artist, renderer, *args, **kwargs)
     96     if renderer._rasterizing:
     97         renderer.stop_rasterizing()

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/artist.py:72, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
     69     if artist.get_agg_filter() is not None:
     70         renderer.start_filter()
---> 72     return draw(artist, renderer)
     73 finally:
     74     if artist.get_agg_filter() is not None:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/figure.py:3140, in Figure.draw(self, renderer)
   3137         # ValueError can occur when resizing a window.
   3139 self.patch.draw(renderer)
-> 3140 mimage._draw_list_compositing_images(
   3141     renderer, self, artists, self.suppressComposite)
   3143 for sfig in self.subfigs:
   3144     sfig.draw(renderer)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/image.py:131, in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
    129 if not_composite or not has_images:
    130     for a in artists:
--> 131         a.draw(renderer)
    132 else:
    133     # Composite any adjacent images together
    134     image_group = []

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/artist.py:72, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
     69     if artist.get_agg_filter() is not None:
     70         renderer.start_filter()
---> 72     return draw(artist, renderer)
     73 finally:
     74     if artist.get_agg_filter() is not None:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/axes/_base.py:3064, in _AxesBase.draw(self, renderer)
   3061 if artists_rasterized:
   3062     _draw_rasterized(self.figure, artists_rasterized, renderer)
-> 3064 mimage._draw_list_compositing_images(
   3065     renderer, self, artists, self.figure.suppressComposite)
   3067 renderer.close_group('axes')
   3068 self.stale = False

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/image.py:131, in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
    129 if not_composite or not has_images:
    130     for a in artists:
--> 131         a.draw(renderer)
    132 else:
    133     # Composite any adjacent images together
    134     image_group = []

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/artist.py:72, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
     69     if artist.get_agg_filter() is not None:
     70         renderer.start_filter()
---> 72     return draw(artist, renderer)
     73 finally:
     74     if artist.get_agg_filter() is not None:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/axis.py:1377, in Axis.draw(self, renderer, *args, **kwargs)
   1374 renderer.open_group(__name__, gid=self.get_gid())
   1376 ticks_to_draw = self._update_ticks()
-> 1377 tlb1, tlb2 = self._get_ticklabel_bboxes(ticks_to_draw, renderer)
   1379 for tick in ticks_to_draw:
   1380     tick.draw(renderer)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/axis.py:1304, in Axis._get_ticklabel_bboxes(self, ticks, renderer)
   1302 if renderer is None:
   1303     renderer = self.figure._get_renderer()
-> 1304 return ([tick.label1.get_window_extent(renderer)
   1305          for tick in ticks if tick.label1.get_visible()],
   1306         [tick.label2.get_window_extent(renderer)
   1307          for tick in ticks if tick.label2.get_visible()])

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/axis.py:1304, in <listcomp>(.0)
   1302 if renderer is None:
   1303     renderer = self.figure._get_renderer()
-> 1304 return ([tick.label1.get_window_extent(renderer)
   1305          for tick in ticks if tick.label1.get_visible()],
   1306         [tick.label2.get_window_extent(renderer)
   1307          for tick in ticks if tick.label2.get_visible()])

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/text.py:959, in Text.get_window_extent(self, renderer, dpi)
    954     raise RuntimeError(
    955         "Cannot get window extent of text w/o renderer. You likely "
    956         "want to call 'figure.draw_without_rendering()' first.")
    958 with cbook._setattr_cm(self.figure, dpi=dpi):
--> 959     bbox, info, descent = self._get_layout(self._renderer)
    960     x, y = self.get_unitless_position()
    961     x, y = self.get_transform().transform((x, y))

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/text.py:378, in Text._get_layout(self, renderer)
    375 ys = []
    377 # Full vertical extent of font, including ascenders and descenders:
--> 378 _, lp_h, lp_d = _get_text_metrics_with_cache(
    379     renderer, "lp", self._fontproperties,
    380     ismath="TeX" if self.get_usetex() else False, dpi=self.figure.dpi)
    381 min_dy = (lp_h - lp_d) * self._linespacing
    383 for i, line in enumerate(lines):

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/text.py:97, in _get_text_metrics_with_cache(renderer, text, fontprop, ismath, dpi)
     94 """Call ``renderer.get_text_width_height_descent``, caching the results."""
     95 # Cached based on a copy of fontprop so that later in-place mutations of
     96 # the passed-in argument do not mess up the cache.
---> 97 return _get_text_metrics_with_cache_impl(
     98     weakref.ref(renderer), text, fontprop.copy(), ismath, dpi)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/text.py:105, in _get_text_metrics_with_cache_impl(renderer_ref, text, fontprop, ismath, dpi)
    101 @functools.lru_cache(4096)
    102 def _get_text_metrics_with_cache_impl(
    103         renderer_ref, text, fontprop, ismath, dpi):
    104     # dpi is unused, but participates in cache invalidation (via the renderer).
--> 105     return renderer_ref().get_text_width_height_descent(text, fontprop, ismath)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/backends/backend_agg.py:226, in RendererAgg.get_text_width_height_descent(self, s, prop, ismath)
    224 _api.check_in_list(["TeX", True, False], ismath=ismath)
    225 if ismath == "TeX":
--> 226     return super().get_text_width_height_descent(s, prop, ismath)
    228 if ismath:
    229     ox, oy, width, height, descent, font_image = \
    230         self.mathtext_parser.parse(s, self.dpi, prop)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/backend_bases.py:645, in RendererBase.get_text_width_height_descent(self, s, prop, ismath)
    641 fontsize = prop.get_size_in_points()
    643 if ismath == 'TeX':
    644     # todo: handle properties
--> 645     return self.get_texmanager().get_text_width_height_descent(
    646         s, fontsize, renderer=self)
    648 dpi = self.points_to_pixels(72)
    649 if ismath:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/texmanager.py:368, in TexManager.get_text_width_height_descent(cls, tex, fontsize, renderer)
    366 if tex.strip() == '':
    367     return 0, 0, 0
--> 368 dvifile = cls.make_dvi(tex, fontsize)
    369 dpi_fraction = renderer.points_to_pixels(1.) if renderer else 1
    370 with dviread.Dvi(dvifile, 72 * dpi_fraction) as dvi:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/texmanager.py:300, in TexManager.make_dvi(cls, tex, fontsize)
    298     with TemporaryDirectory(dir=cwd) as tmpdir:
    299         tmppath = Path(tmpdir)
--> 300         cls._run_checked_subprocess(
    301             ["latex", "-interaction=nonstopmode", "--halt-on-error",
    302              f"--output-directory={tmppath.name}",
    303              f"{texfile.name}"], tex, cwd=cwd)
    304         (tmppath / Path(dvifile).name).replace(dvifile)
    305 return dvifile

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/texmanager.py:259, in TexManager._run_checked_subprocess(cls, command, tex, cwd)
    255     report = subprocess.check_output(
    256         command, cwd=cwd if cwd is not None else cls.texcache,
    257         stderr=subprocess.STDOUT)
    258 except FileNotFoundError as exc:
--> 259     raise RuntimeError(
    260         'Failed to process string with tex because {} could not be '
    261         'found'.format(command[0])) from exc
    262 except subprocess.CalledProcessError as exc:
    263     raise RuntimeError(
    264         '{prog} was not able to process the following string:\n'
    265         '{tex!r}\n\n'
   (...)
    272             exc=exc.output.decode('utf-8', 'backslashreplace'))
    273         ) from None

RuntimeError: Failed to process string with tex because latex could not be found
---------------------------------------------------------------------------
FileNotFoundError                         Traceback (most recent call last)
File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/texmanager.py:255, in TexManager._run_checked_subprocess(cls, command, tex, cwd)
    254 try:
--> 255     report = subprocess.check_output(
    256         command, cwd=cwd if cwd is not None else cls.texcache,
    257         stderr=subprocess.STDOUT)
    258 except FileNotFoundError as exc:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/subprocess.py:421, in check_output(timeout, *popenargs, **kwargs)
    419     kwargs['input'] = empty
--> 421 return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
    422            **kwargs).stdout

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/subprocess.py:503, in run(input, capture_output, timeout, check, *popenargs, **kwargs)
    501     kwargs['stderr'] = PIPE
--> 503 with Popen(*popenargs, **kwargs) as process:
    504     try:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/subprocess.py:971, in Popen.__init__(self, args, bufsize, executable, stdin, stdout, stderr, preexec_fn, close_fds, shell, cwd, env, universal_newlines, startupinfo, creationflags, restore_signals, start_new_session, pass_fds, user, group, extra_groups, encoding, errors, text, umask, pipesize)
    968             self.stderr = io.TextIOWrapper(self.stderr,
    969                     encoding=encoding, errors=errors)
--> 971     self._execute_child(args, executable, preexec_fn, close_fds,
    972                         pass_fds, cwd, env,
    973                         startupinfo, creationflags, shell,
    974                         p2cread, p2cwrite,
    975                         c2pread, c2pwrite,
    976                         errread, errwrite,
    977                         restore_signals,
    978                         gid, gids, uid, umask,
    979                         start_new_session)
    980 except:
    981     # Cleanup if the child failed starting.

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/subprocess.py:1863, in Popen._execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session)
   1862         err_msg = os.strerror(errno_num)
-> 1863     raise child_exception_type(errno_num, err_msg, err_filename)
   1864 raise child_exception_type(err_msg)

FileNotFoundError: [Errno 2] No such file or directory: 'latex'

The above exception was the direct cause of the following exception:

RuntimeError                              Traceback (most recent call last)
File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/IPython/core/formatters.py:340, in BaseFormatter.__call__(self, obj)
    338     pass
    339 else:
--> 340     return printer(obj)
    341 # Finally look for special method names
    342 method = get_real_method(obj, self.print_method)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/IPython/core/pylabtools.py:152, in print_figure(fig, fmt, bbox_inches, base64, **kwargs)
    149     from matplotlib.backend_bases import FigureCanvasBase
    150     FigureCanvasBase(fig)
--> 152 fig.canvas.print_figure(bytes_io, **kw)
    153 data = bytes_io.getvalue()
    154 if fmt == 'svg':

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/backend_bases.py:2342, in FigureCanvasBase.print_figure(self, filename, dpi, facecolor, edgecolor, orientation, format, bbox_inches, pad_inches, bbox_extra_artists, backend, **kwargs)
   2336     renderer = _get_renderer(
   2337         self.figure,
   2338         functools.partial(
   2339             print_method, orientation=orientation)
   2340     )
   2341     with getattr(renderer, "_draw_disabled", nullcontext)():
-> 2342         self.figure.draw(renderer)
   2344 if bbox_inches:
   2345     if bbox_inches == "tight":

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/artist.py:95, in _finalize_rasterization.<locals>.draw_wrapper(artist, renderer, *args, **kwargs)
     93 @wraps(draw)
     94 def draw_wrapper(artist, renderer, *args, **kwargs):
---> 95     result = draw(artist, renderer, *args, **kwargs)
     96     if renderer._rasterizing:
     97         renderer.stop_rasterizing()

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/artist.py:72, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
     69     if artist.get_agg_filter() is not None:
     70         renderer.start_filter()
---> 72     return draw(artist, renderer)
     73 finally:
     74     if artist.get_agg_filter() is not None:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/figure.py:3140, in Figure.draw(self, renderer)
   3137         # ValueError can occur when resizing a window.
   3139 self.patch.draw(renderer)
-> 3140 mimage._draw_list_compositing_images(
   3141     renderer, self, artists, self.suppressComposite)
   3143 for sfig in self.subfigs:
   3144     sfig.draw(renderer)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/image.py:131, in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
    129 if not_composite or not has_images:
    130     for a in artists:
--> 131         a.draw(renderer)
    132 else:
    133     # Composite any adjacent images together
    134     image_group = []

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/artist.py:72, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
     69     if artist.get_agg_filter() is not None:
     70         renderer.start_filter()
---> 72     return draw(artist, renderer)
     73 finally:
     74     if artist.get_agg_filter() is not None:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/axes/_base.py:3064, in _AxesBase.draw(self, renderer)
   3061 if artists_rasterized:
   3062     _draw_rasterized(self.figure, artists_rasterized, renderer)
-> 3064 mimage._draw_list_compositing_images(
   3065     renderer, self, artists, self.figure.suppressComposite)
   3067 renderer.close_group('axes')
   3068 self.stale = False

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/image.py:131, in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
    129 if not_composite or not has_images:
    130     for a in artists:
--> 131         a.draw(renderer)
    132 else:
    133     # Composite any adjacent images together
    134     image_group = []

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/artist.py:72, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
     69     if artist.get_agg_filter() is not None:
     70         renderer.start_filter()
---> 72     return draw(artist, renderer)
     73 finally:
     74     if artist.get_agg_filter() is not None:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/axis.py:1377, in Axis.draw(self, renderer, *args, **kwargs)
   1374 renderer.open_group(__name__, gid=self.get_gid())
   1376 ticks_to_draw = self._update_ticks()
-> 1377 tlb1, tlb2 = self._get_ticklabel_bboxes(ticks_to_draw, renderer)
   1379 for tick in ticks_to_draw:
   1380     tick.draw(renderer)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/axis.py:1304, in Axis._get_ticklabel_bboxes(self, ticks, renderer)
   1302 if renderer is None:
   1303     renderer = self.figure._get_renderer()
-> 1304 return ([tick.label1.get_window_extent(renderer)
   1305          for tick in ticks if tick.label1.get_visible()],
   1306         [tick.label2.get_window_extent(renderer)
   1307          for tick in ticks if tick.label2.get_visible()])

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/axis.py:1304, in <listcomp>(.0)
   1302 if renderer is None:
   1303     renderer = self.figure._get_renderer()
-> 1304 return ([tick.label1.get_window_extent(renderer)
   1305          for tick in ticks if tick.label1.get_visible()],
   1306         [tick.label2.get_window_extent(renderer)
   1307          for tick in ticks if tick.label2.get_visible()])

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/text.py:959, in Text.get_window_extent(self, renderer, dpi)
    954     raise RuntimeError(
    955         "Cannot get window extent of text w/o renderer. You likely "
    956         "want to call 'figure.draw_without_rendering()' first.")
    958 with cbook._setattr_cm(self.figure, dpi=dpi):
--> 959     bbox, info, descent = self._get_layout(self._renderer)
    960     x, y = self.get_unitless_position()
    961     x, y = self.get_transform().transform((x, y))

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/text.py:378, in Text._get_layout(self, renderer)
    375 ys = []
    377 # Full vertical extent of font, including ascenders and descenders:
--> 378 _, lp_h, lp_d = _get_text_metrics_with_cache(
    379     renderer, "lp", self._fontproperties,
    380     ismath="TeX" if self.get_usetex() else False, dpi=self.figure.dpi)
    381 min_dy = (lp_h - lp_d) * self._linespacing
    383 for i, line in enumerate(lines):

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/text.py:97, in _get_text_metrics_with_cache(renderer, text, fontprop, ismath, dpi)
     94 """Call ``renderer.get_text_width_height_descent``, caching the results."""
     95 # Cached based on a copy of fontprop so that later in-place mutations of
     96 # the passed-in argument do not mess up the cache.
---> 97 return _get_text_metrics_with_cache_impl(
     98     weakref.ref(renderer), text, fontprop.copy(), ismath, dpi)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/text.py:105, in _get_text_metrics_with_cache_impl(renderer_ref, text, fontprop, ismath, dpi)
    101 @functools.lru_cache(4096)
    102 def _get_text_metrics_with_cache_impl(
    103         renderer_ref, text, fontprop, ismath, dpi):
    104     # dpi is unused, but participates in cache invalidation (via the renderer).
--> 105     return renderer_ref().get_text_width_height_descent(text, fontprop, ismath)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/backends/backend_agg.py:226, in RendererAgg.get_text_width_height_descent(self, s, prop, ismath)
    224 _api.check_in_list(["TeX", True, False], ismath=ismath)
    225 if ismath == "TeX":
--> 226     return super().get_text_width_height_descent(s, prop, ismath)
    228 if ismath:
    229     ox, oy, width, height, descent, font_image = \
    230         self.mathtext_parser.parse(s, self.dpi, prop)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/backend_bases.py:645, in RendererBase.get_text_width_height_descent(self, s, prop, ismath)
    641 fontsize = prop.get_size_in_points()
    643 if ismath == 'TeX':
    644     # todo: handle properties
--> 645     return self.get_texmanager().get_text_width_height_descent(
    646         s, fontsize, renderer=self)
    648 dpi = self.points_to_pixels(72)
    649 if ismath:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/texmanager.py:368, in TexManager.get_text_width_height_descent(cls, tex, fontsize, renderer)
    366 if tex.strip() == '':
    367     return 0, 0, 0
--> 368 dvifile = cls.make_dvi(tex, fontsize)
    369 dpi_fraction = renderer.points_to_pixels(1.) if renderer else 1
    370 with dviread.Dvi(dvifile, 72 * dpi_fraction) as dvi:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/texmanager.py:300, in TexManager.make_dvi(cls, tex, fontsize)
    298     with TemporaryDirectory(dir=cwd) as tmpdir:
    299         tmppath = Path(tmpdir)
--> 300         cls._run_checked_subprocess(
    301             ["latex", "-interaction=nonstopmode", "--halt-on-error",
    302              f"--output-directory={tmppath.name}",
    303              f"{texfile.name}"], tex, cwd=cwd)
    304         (tmppath / Path(dvifile).name).replace(dvifile)
    305 return dvifile

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/texmanager.py:259, in TexManager._run_checked_subprocess(cls, command, tex, cwd)
    255     report = subprocess.check_output(
    256         command, cwd=cwd if cwd is not None else cls.texcache,
    257         stderr=subprocess.STDOUT)
    258 except FileNotFoundError as exc:
--> 259     raise RuntimeError(
    260         'Failed to process string with tex because {} could not be '
    261         'found'.format(command[0])) from exc
    262 except subprocess.CalledProcessError as exc:
    263     raise RuntimeError(
    264         '{prog} was not able to process the following string:\n'
    265         '{tex!r}\n\n'
   (...)
    272             exc=exc.output.decode('utf-8', 'backslashreplace'))
    273         ) from None

RuntimeError: Failed to process string with tex because latex could not be found
<Figure size 900x550 with 1 Axes>