Analysing Samples¶
Download this as a Jupyter notebook
This guide covers how to use pyXla to conduct landscape analysis.
The first step is to load a sample:
from pyxla.sampling import HilbertCurveSampler
from pyxla import load_data
sampler = HilbertCurveSampler(
sample_size=100, dim=2, return_neighbourhood=True
)
sample = {
"X": sampler,
"F": lambda x: (x**2).sum(),
"V": lambda x: ((x**2).sum() - 3),
"D": lambda x1, x2: ((x1 - x2)**2).sum(), #must take a pair of arguments and real number
# N file is provided by the sampler since return_neighbourhood=True
}
load_data(sample)
The next step, is to import the explainable landscape analysis (xLA) feature of choice. For instance we import the distr_f (distribution of objective values) below:
from pyxla import distr_f
Lastly, invoke the imported feature.
feat, plot = distr_f(sample)
Error in callback <function _draw_all_if_interactive at 0x786ba5423110> (for post_execute), with arguments args (),kwargs {}:
---------------------------------------------------------------------------
FileNotFoundError Traceback (most recent call last)
File /usr/local/lib/python3.14/site-packages/matplotlib/texmanager.py:258, in TexManager._run_checked_subprocess(cls, command, tex, cwd)
257 try:
--> 258 report = subprocess.check_output(
259 command, cwd=cwd if cwd is not None else cls._cache_dir,
260 stderr=subprocess.STDOUT)
261 except subprocess.CalledProcessError as exc:
File /usr/local/lib/python3.14/subprocess.py:473, in check_output(timeout, *popenargs, **kwargs)
471 kwargs['input'] = empty
--> 473 return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
474 **kwargs).stdout
File /usr/local/lib/python3.14/subprocess.py:555, in run(input, capture_output, timeout, check, *popenargs, **kwargs)
553 kwargs['stderr'] = PIPE
--> 555 with Popen(*popenargs, **kwargs) as process:
556 try:
File /usr/local/lib/python3.14/subprocess.py:1039, 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, process_group)
1036 self.stderr = io.TextIOWrapper(self.stderr,
1037 encoding=encoding, errors=errors)
-> 1039 self._execute_child(args, executable, preexec_fn, close_fds,
1040 pass_fds, cwd, env,
1041 startupinfo, creationflags, shell,
1042 p2cread, p2cwrite,
1043 c2pread, c2pwrite,
1044 errread, errwrite,
1045 restore_signals,
1046 gid, gids, uid, umask,
1047 start_new_session, process_group)
1048 except:
1049 # Cleanup if the child failed starting.
File /usr/local/lib/python3.14/subprocess.py:1990, 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, process_group)
1989 if err_filename is not None:
-> 1990 raise child_exception_type(errno_num, err_msg, err_filename)
1991 else:
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/local/lib/python3.14/site-packages/matplotlib/pyplot.py:300, in _draw_all_if_interactive()
298 def _draw_all_if_interactive() -> None:
299 if matplotlib.is_interactive():
--> 300 draw_all()
File /usr/local/lib/python3.14/site-packages/matplotlib/_pylab_helpers.py:133, in Gcf.draw_all(cls, force)
131 for manager in cls.get_all_fig_managers():
132 if force or manager.canvas.figure.stale:
--> 133 manager.canvas.draw_idle()
File /usr/local/lib/python3.14/site-packages/matplotlib/backend_bases.py:1989, in FigureCanvasBase.draw_idle(self, *args, **kwargs)
1987 if not self._is_idle_drawing:
1988 with self._idle_draw_cntx():
-> 1989 self.draw(*args, **kwargs)
File /usr/local/lib/python3.14/site-packages/matplotlib/backends/backend_agg.py:438, in FigureCanvasAgg.draw(self)
435 # Acquire a lock on the shared font cache.
436 with (self.toolbar._wait_cursor_for_draw_cm() if self.toolbar
437 else nullcontext()):
--> 438 self.figure.draw(self.renderer)
439 # A GUI class may be need to update a window using this draw, so
440 # don't forget to call the superclass.
441 super().draw()
File /usr/local/lib/python3.14/site-packages/matplotlib/artist.py:94, in _finalize_rasterization.<locals>.draw_wrapper(artist, renderer, *args, **kwargs)
92 @wraps(draw)
93 def draw_wrapper(artist, renderer, *args, **kwargs):
---> 94 result = draw(artist, renderer, *args, **kwargs)
95 if renderer._rasterizing:
96 renderer.stop_rasterizing()
File /usr/local/lib/python3.14/site-packages/matplotlib/artist.py:71, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
68 if artist.get_agg_filter() is not None:
69 renderer.start_filter()
---> 71 return draw(artist, renderer)
72 finally:
73 if artist.get_agg_filter() is not None:
File /usr/local/lib/python3.14/site-packages/matplotlib/figure.py:3276, in Figure.draw(self, renderer)
3274 if self.axes and self.get_layout_engine() is not None:
3275 try:
-> 3276 self.get_layout_engine().execute(self)
3277 except ValueError:
3278 pass
File /usr/local/lib/python3.14/site-packages/matplotlib/layout_engine.py:278, in ConstrainedLayoutEngine.execute(self, fig)
275 w_pad = self._params['w_pad'] / width
276 h_pad = self._params['h_pad'] / height
--> 278 return do_constrained_layout(fig, w_pad=w_pad, h_pad=h_pad,
279 wspace=self._params['wspace'],
280 hspace=self._params['hspace'],
281 rect=self._params['rect'],
282 compress=self._compress)
File /usr/local/lib/python3.14/site-packages/matplotlib/_constrained_layout.py:116, in do_constrained_layout(fig, h_pad, w_pad, hspace, wspace, rect, compress)
106 return
108 for _ in range(2):
109 # do the algorithm twice. This has to be done because decorations
110 # change size after the first re-position (i.e. x/yticklabels get
(...) 114 # make margins for all the Axes and subfigures in the
115 # figure. Add margins for colorbars...
--> 116 make_layout_margins(layoutgrids, fig, renderer, h_pad=h_pad,
117 w_pad=w_pad, hspace=hspace, wspace=wspace)
118 make_margin_suptitles(layoutgrids, fig, renderer, h_pad=h_pad,
119 w_pad=w_pad)
121 # if a layout is such that a columns (or rows) margin has no
122 # constraints, we need to make all such instances in the grid
123 # match in margin size.
File /usr/local/lib/python3.14/site-packages/matplotlib/_constrained_layout.py:389, in make_layout_margins(layoutgrids, fig, renderer, w_pad, h_pad, hspace, wspace)
385 return
387 margin = get_margin_from_padding(ax, w_pad=w_pad, h_pad=h_pad,
388 hspace=hspace, wspace=wspace)
--> 389 pos, bbox = get_pos_and_bbox(ax, renderer)
390 # the margin is the distance between the bounding box of the Axes
391 # and its position (plus the padding from above)
392 margin['left'] += pos.x0 - bbox.x0
File /usr/local/lib/python3.14/site-packages/matplotlib/_constrained_layout.py:637, in get_pos_and_bbox(ax, renderer)
635 # pos is in panel co-ords, but we need in figure for the layout
636 pos = pos.transformed(fig.transSubfigure - fig.transFigure)
--> 637 tightbbox = martist._get_tightbbox_for_layout_only(ax, renderer)
638 if tightbbox is None:
639 bbox = pos
File /usr/local/lib/python3.14/site-packages/matplotlib/artist.py:1485, in _get_tightbbox_for_layout_only(obj, *args, **kwargs)
1479 """
1480 Matplotlib's `.Axes.get_tightbbox` and `.Axis.get_tightbbox` support a
1481 *for_layout_only* kwarg; this helper tries to use the kwarg but skips it
1482 when encountering third-party subclasses that do not support it.
1483 """
1484 try:
-> 1485 return obj.get_tightbbox(*args, **{**kwargs, "for_layout_only": True})
1486 except TypeError:
1487 return obj.get_tightbbox(*args, **kwargs)
File /usr/local/lib/python3.14/site-packages/matplotlib/axes/_base.py:4758, in _AxesBase.get_tightbbox(self, renderer, call_axes_locator, bbox_extra_artists, for_layout_only)
4756 if self.axison and axis.get_visible():
4757 if for_layout_only:
-> 4758 ba = martist._get_tightbbox_for_layout_only(axis, renderer)
4759 else:
4760 ba = axis.get_tightbbox(renderer)
File /usr/local/lib/python3.14/site-packages/matplotlib/artist.py:1485, in _get_tightbbox_for_layout_only(obj, *args, **kwargs)
1479 """
1480 Matplotlib's `.Axes.get_tightbbox` and `.Axis.get_tightbbox` support a
1481 *for_layout_only* kwarg; this helper tries to use the kwarg but skips it
1482 when encountering third-party subclasses that do not support it.
1483 """
1484 try:
-> 1485 return obj.get_tightbbox(*args, **{**kwargs, "for_layout_only": True})
1486 except TypeError:
1487 return obj.get_tightbbox(*args, **kwargs)
File /usr/local/lib/python3.14/site-packages/matplotlib/axis.py:1427, in Axis.get_tightbbox(self, renderer, for_layout_only)
1424 renderer = self.get_figure(root=True)._get_renderer()
1425 ticks_to_draw = self._update_ticks()
-> 1427 self._update_label_position(renderer)
1429 # go back to just this axis's tick labels
1430 tlb1, tlb2 = self._get_ticklabel_bboxes(ticks_to_draw, renderer)
File /usr/local/lib/python3.14/site-packages/matplotlib/axis.py:2615, in XAxis._update_label_position(self, renderer)
2611 return
2613 # get bounding boxes for this axis and any siblings
2614 # that have been set by `fig.align_xlabels()`
-> 2615 bboxes, bboxes2 = self._get_tick_boxes_siblings(renderer=renderer)
2616 x, y = self.label.get_position()
2618 if self.label_position == 'bottom':
2619 # Union with extents of the bottom spine if present, of the axes otherwise.
File /usr/local/lib/python3.14/site-packages/matplotlib/axis.py:2403, in Axis._get_tick_boxes_siblings(self, renderer)
2401 axis = ax._axis_map[name]
2402 ticks_to_draw = axis._update_ticks()
-> 2403 tlb, tlb2 = axis._get_ticklabel_bboxes(ticks_to_draw, renderer)
2404 bboxes.extend(tlb)
2405 bboxes2.extend(tlb2)
File /usr/local/lib/python3.14/site-packages/matplotlib/axis.py:1404, in Axis._get_ticklabel_bboxes(self, ticks, renderer)
1402 def _get_ticklabel_bboxes(self, ticks, renderer):
1403 """Return lists of bboxes for ticks' label1's and label2's."""
-> 1404 return ([tick.label1.get_window_extent(renderer)
1405 for tick in ticks
1406 if tick.label1.get_visible() and tick.label1.get_in_layout()],
1407 [tick.label2.get_window_extent(renderer)
1408 for tick in ticks
1409 if tick.label2.get_visible() and tick.label2.get_in_layout()])
File /usr/local/lib/python3.14/site-packages/matplotlib/text.py:1076, in Text.get_window_extent(self, renderer, dpi)
1071 raise RuntimeError(
1072 "Cannot get window extent of text w/o renderer. You likely "
1073 "want to call 'figure.draw_without_rendering()' first.")
1075 with cbook._setattr_cm(fig, dpi=dpi):
-> 1076 bbox, _, _ = self._get_layout(self._renderer)
1077 x, y = self.get_unitless_position()
1078 x, y = self.get_transform().transform((x, y))
File /usr/local/lib/python3.14/site-packages/matplotlib/text.py:465, in Text._get_layout(self, renderer)
462 break
463 if None in (min_ascent, min_descent):
464 # Fallback to font measurement.
--> 465 _, h, min_descent = _get_text_metrics_with_cache(
466 renderer, "lp", self._fontproperties,
467 ismath="TeX" if self.get_usetex() else False,
468 dpi=dpi)
469 min_ascent = h - min_descent
470 line_gap = 0
File /usr/local/lib/python3.14/site-packages/matplotlib/text.py:59, in _get_text_metrics_with_cache(renderer, text, fontprop, ismath, dpi)
52 get_text_metrics = _get_text_metrics_function(renderer)
53 # call the function to compute the metrics and return
54 #
55 # We pass a copy of the fontprop because FontProperties is both mutable and
56 # has a `__hash__` that depends on that mutable state. This is not ideal
57 # as it means the hash of an object is not stable over time which leads to
58 # very confusing behavior when used as keys in dictionaries or hashes.
---> 59 return get_text_metrics(text, fontprop.copy(), ismath, dpi)
File /usr/local/lib/python3.14/site-packages/matplotlib/text.py:125, in _get_text_metrics_function.<locals>._text_metrics(text, fontprop, ismath, dpi)
120 raise RuntimeError(
121 "Trying to get text metrics for a renderer that no longer exists. "
122 "This should never happen and is evidence of a bug elsewhere."
123 )
124 # do the actual method call we need and return the result
--> 125 return local_renderer.get_text_width_height_descent(text, fontprop, ismath)
File /usr/local/lib/python3.14/site-packages/matplotlib/backends/backend_agg.py:256, in RendererAgg.get_text_width_height_descent(self, s, prop, ismath)
254 _api.check_in_list(["TeX", True, False], ismath=ismath)
255 if ismath == "TeX":
--> 256 return super().get_text_width_height_descent(s, prop, ismath)
258 if ismath:
259 parse = self.mathtext_parser.parse(s, self.dpi, prop)
File /usr/local/lib/python3.14/site-packages/matplotlib/backend_bases.py:589, in RendererBase.get_text_width_height_descent(self, s, prop, ismath)
585 fontsize = prop.get_size_in_points()
587 if ismath == 'TeX':
588 # todo: handle properties
--> 589 return self.get_texmanager().get_text_width_height_descent(
590 s, fontsize, renderer=self)
592 dpi = self.points_to_pixels(72)
593 if ismath:
File /usr/local/lib/python3.14/site-packages/matplotlib/texmanager.py:369, in TexManager.get_text_width_height_descent(cls, tex, fontsize, renderer)
367 if tex.strip() == '':
368 return 0, 0, 0
--> 369 dvipath = cls.make_dvi(tex, fontsize)
370 dpi_fraction = renderer.points_to_pixels(1.) if renderer else 1
371 with dviread.Dvi(dvipath, 72 * dpi_fraction) as dvi:
File /usr/local/lib/python3.14/site-packages/matplotlib/texmanager.py:301, in TexManager.make_dvi(cls, tex, fontsize)
298 with TemporaryDirectory(dir=dvipath.parent) as tmpdir:
299 Path(tmpdir, "file.tex").write_text(
300 cls._get_tex_source(tex, fontsize), encoding='utf-8')
--> 301 cls._run_checked_subprocess(
302 ["latex", "-interaction=nonstopmode", "-halt-on-error",
303 "-no-shell-escape", "file.tex"], tex, cwd=tmpdir)
304 Path(tmpdir, "file.dvi").replace(dvipath)
305 # Also move the tex source to the main cache directory, but
306 # only for backcompat.
File /usr/local/lib/python3.14/site-packages/matplotlib/texmanager.py:274, in TexManager._run_checked_subprocess(cls, command, tex, cwd)
262 raise RuntimeError(
263 '{prog} was not able to process the following string:\n'
264 '{tex!r}\n\n'
(...) 271 exc=exc.output.decode('utf-8', 'backslashreplace'))
272 ) from None
273 except (FileNotFoundError, OSError) as exc:
--> 274 raise RuntimeError(
275 f'Failed to process string with tex because {command[0]} '
276 'could not be found') from exc
277 _log.debug(report)
278 return report
RuntimeError: Failed to process string with tex because latex could not be found
---------------------------------------------------------------------------
FileNotFoundError Traceback (most recent call last)
File /usr/local/lib/python3.14/site-packages/matplotlib/texmanager.py:258, in TexManager._run_checked_subprocess(cls, command, tex, cwd)
257 try:
--> 258 report = subprocess.check_output(
259 command, cwd=cwd if cwd is not None else cls._cache_dir,
260 stderr=subprocess.STDOUT)
261 except subprocess.CalledProcessError as exc:
File /usr/local/lib/python3.14/subprocess.py:473, in check_output(timeout, *popenargs, **kwargs)
471 kwargs['input'] = empty
--> 473 return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
474 **kwargs).stdout
File /usr/local/lib/python3.14/subprocess.py:555, in run(input, capture_output, timeout, check, *popenargs, **kwargs)
553 kwargs['stderr'] = PIPE
--> 555 with Popen(*popenargs, **kwargs) as process:
556 try:
File /usr/local/lib/python3.14/subprocess.py:1039, 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, process_group)
1036 self.stderr = io.TextIOWrapper(self.stderr,
1037 encoding=encoding, errors=errors)
-> 1039 self._execute_child(args, executable, preexec_fn, close_fds,
1040 pass_fds, cwd, env,
1041 startupinfo, creationflags, shell,
1042 p2cread, p2cwrite,
1043 c2pread, c2pwrite,
1044 errread, errwrite,
1045 restore_signals,
1046 gid, gids, uid, umask,
1047 start_new_session, process_group)
1048 except:
1049 # Cleanup if the child failed starting.
File /usr/local/lib/python3.14/subprocess.py:1990, 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, process_group)
1989 if err_filename is not None:
-> 1990 raise child_exception_type(errno_num, err_msg, err_filename)
1991 else:
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/local/lib/python3.14/site-packages/matplotlib/backend_bases.py:2257, in FigureCanvasBase.print_figure(self, filename, dpi, facecolor, edgecolor, orientation, format, bbox_inches, pad_inches, bbox_extra_artists, backend, **kwargs)
2254 # we do this instead of `self.figure.draw_without_rendering`
2255 # so that we can inject the orientation
2256 with getattr(renderer, "_draw_disabled", nullcontext)():
-> 2257 self.figure.draw(renderer)
2258 else:
2259 renderer = None
File /usr/local/lib/python3.14/site-packages/matplotlib/artist.py:94, in _finalize_rasterization.<locals>.draw_wrapper(artist, renderer, *args, **kwargs)
92 @wraps(draw)
93 def draw_wrapper(artist, renderer, *args, **kwargs):
---> 94 result = draw(artist, renderer, *args, **kwargs)
95 if renderer._rasterizing:
96 renderer.stop_rasterizing()
File /usr/local/lib/python3.14/site-packages/matplotlib/artist.py:71, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
68 if artist.get_agg_filter() is not None:
69 renderer.start_filter()
---> 71 return draw(artist, renderer)
72 finally:
73 if artist.get_agg_filter() is not None:
File /usr/local/lib/python3.14/site-packages/matplotlib/figure.py:3276, in Figure.draw(self, renderer)
3274 if self.axes and self.get_layout_engine() is not None:
3275 try:
-> 3276 self.get_layout_engine().execute(self)
3277 except ValueError:
3278 pass
File /usr/local/lib/python3.14/site-packages/matplotlib/layout_engine.py:278, in ConstrainedLayoutEngine.execute(self, fig)
275 w_pad = self._params['w_pad'] / width
276 h_pad = self._params['h_pad'] / height
--> 278 return do_constrained_layout(fig, w_pad=w_pad, h_pad=h_pad,
279 wspace=self._params['wspace'],
280 hspace=self._params['hspace'],
281 rect=self._params['rect'],
282 compress=self._compress)
File /usr/local/lib/python3.14/site-packages/matplotlib/_constrained_layout.py:116, in do_constrained_layout(fig, h_pad, w_pad, hspace, wspace, rect, compress)
106 return
108 for _ in range(2):
109 # do the algorithm twice. This has to be done because decorations
110 # change size after the first re-position (i.e. x/yticklabels get
(...) 114 # make margins for all the Axes and subfigures in the
115 # figure. Add margins for colorbars...
--> 116 make_layout_margins(layoutgrids, fig, renderer, h_pad=h_pad,
117 w_pad=w_pad, hspace=hspace, wspace=wspace)
118 make_margin_suptitles(layoutgrids, fig, renderer, h_pad=h_pad,
119 w_pad=w_pad)
121 # if a layout is such that a columns (or rows) margin has no
122 # constraints, we need to make all such instances in the grid
123 # match in margin size.
File /usr/local/lib/python3.14/site-packages/matplotlib/_constrained_layout.py:389, in make_layout_margins(layoutgrids, fig, renderer, w_pad, h_pad, hspace, wspace)
385 return
387 margin = get_margin_from_padding(ax, w_pad=w_pad, h_pad=h_pad,
388 hspace=hspace, wspace=wspace)
--> 389 pos, bbox = get_pos_and_bbox(ax, renderer)
390 # the margin is the distance between the bounding box of the Axes
391 # and its position (plus the padding from above)
392 margin['left'] += pos.x0 - bbox.x0
File /usr/local/lib/python3.14/site-packages/matplotlib/_constrained_layout.py:637, in get_pos_and_bbox(ax, renderer)
635 # pos is in panel co-ords, but we need in figure for the layout
636 pos = pos.transformed(fig.transSubfigure - fig.transFigure)
--> 637 tightbbox = martist._get_tightbbox_for_layout_only(ax, renderer)
638 if tightbbox is None:
639 bbox = pos
File /usr/local/lib/python3.14/site-packages/matplotlib/artist.py:1485, in _get_tightbbox_for_layout_only(obj, *args, **kwargs)
1479 """
1480 Matplotlib's `.Axes.get_tightbbox` and `.Axis.get_tightbbox` support a
1481 *for_layout_only* kwarg; this helper tries to use the kwarg but skips it
1482 when encountering third-party subclasses that do not support it.
1483 """
1484 try:
-> 1485 return obj.get_tightbbox(*args, **{**kwargs, "for_layout_only": True})
1486 except TypeError:
1487 return obj.get_tightbbox(*args, **kwargs)
File /usr/local/lib/python3.14/site-packages/matplotlib/axes/_base.py:4758, in _AxesBase.get_tightbbox(self, renderer, call_axes_locator, bbox_extra_artists, for_layout_only)
4756 if self.axison and axis.get_visible():
4757 if for_layout_only:
-> 4758 ba = martist._get_tightbbox_for_layout_only(axis, renderer)
4759 else:
4760 ba = axis.get_tightbbox(renderer)
File /usr/local/lib/python3.14/site-packages/matplotlib/artist.py:1485, in _get_tightbbox_for_layout_only(obj, *args, **kwargs)
1479 """
1480 Matplotlib's `.Axes.get_tightbbox` and `.Axis.get_tightbbox` support a
1481 *for_layout_only* kwarg; this helper tries to use the kwarg but skips it
1482 when encountering third-party subclasses that do not support it.
1483 """
1484 try:
-> 1485 return obj.get_tightbbox(*args, **{**kwargs, "for_layout_only": True})
1486 except TypeError:
1487 return obj.get_tightbbox(*args, **kwargs)
File /usr/local/lib/python3.14/site-packages/matplotlib/axis.py:1427, in Axis.get_tightbbox(self, renderer, for_layout_only)
1424 renderer = self.get_figure(root=True)._get_renderer()
1425 ticks_to_draw = self._update_ticks()
-> 1427 self._update_label_position(renderer)
1429 # go back to just this axis's tick labels
1430 tlb1, tlb2 = self._get_ticklabel_bboxes(ticks_to_draw, renderer)
File /usr/local/lib/python3.14/site-packages/matplotlib/axis.py:2615, in XAxis._update_label_position(self, renderer)
2611 return
2613 # get bounding boxes for this axis and any siblings
2614 # that have been set by `fig.align_xlabels()`
-> 2615 bboxes, bboxes2 = self._get_tick_boxes_siblings(renderer=renderer)
2616 x, y = self.label.get_position()
2618 if self.label_position == 'bottom':
2619 # Union with extents of the bottom spine if present, of the axes otherwise.
File /usr/local/lib/python3.14/site-packages/matplotlib/axis.py:2403, in Axis._get_tick_boxes_siblings(self, renderer)
2401 axis = ax._axis_map[name]
2402 ticks_to_draw = axis._update_ticks()
-> 2403 tlb, tlb2 = axis._get_ticklabel_bboxes(ticks_to_draw, renderer)
2404 bboxes.extend(tlb)
2405 bboxes2.extend(tlb2)
File /usr/local/lib/python3.14/site-packages/matplotlib/axis.py:1404, in Axis._get_ticklabel_bboxes(self, ticks, renderer)
1402 def _get_ticklabel_bboxes(self, ticks, renderer):
1403 """Return lists of bboxes for ticks' label1's and label2's."""
-> 1404 return ([tick.label1.get_window_extent(renderer)
1405 for tick in ticks
1406 if tick.label1.get_visible() and tick.label1.get_in_layout()],
1407 [tick.label2.get_window_extent(renderer)
1408 for tick in ticks
1409 if tick.label2.get_visible() and tick.label2.get_in_layout()])
File /usr/local/lib/python3.14/site-packages/matplotlib/text.py:1076, in Text.get_window_extent(self, renderer, dpi)
1071 raise RuntimeError(
1072 "Cannot get window extent of text w/o renderer. You likely "
1073 "want to call 'figure.draw_without_rendering()' first.")
1075 with cbook._setattr_cm(fig, dpi=dpi):
-> 1076 bbox, _, _ = self._get_layout(self._renderer)
1077 x, y = self.get_unitless_position()
1078 x, y = self.get_transform().transform((x, y))
File /usr/local/lib/python3.14/site-packages/matplotlib/text.py:465, in Text._get_layout(self, renderer)
462 break
463 if None in (min_ascent, min_descent):
464 # Fallback to font measurement.
--> 465 _, h, min_descent = _get_text_metrics_with_cache(
466 renderer, "lp", self._fontproperties,
467 ismath="TeX" if self.get_usetex() else False,
468 dpi=dpi)
469 min_ascent = h - min_descent
470 line_gap = 0
File /usr/local/lib/python3.14/site-packages/matplotlib/text.py:59, in _get_text_metrics_with_cache(renderer, text, fontprop, ismath, dpi)
52 get_text_metrics = _get_text_metrics_function(renderer)
53 # call the function to compute the metrics and return
54 #
55 # We pass a copy of the fontprop because FontProperties is both mutable and
56 # has a `__hash__` that depends on that mutable state. This is not ideal
57 # as it means the hash of an object is not stable over time which leads to
58 # very confusing behavior when used as keys in dictionaries or hashes.
---> 59 return get_text_metrics(text, fontprop.copy(), ismath, dpi)
File /usr/local/lib/python3.14/site-packages/matplotlib/text.py:125, in _get_text_metrics_function.<locals>._text_metrics(text, fontprop, ismath, dpi)
120 raise RuntimeError(
121 "Trying to get text metrics for a renderer that no longer exists. "
122 "This should never happen and is evidence of a bug elsewhere."
123 )
124 # do the actual method call we need and return the result
--> 125 return local_renderer.get_text_width_height_descent(text, fontprop, ismath)
File /usr/local/lib/python3.14/site-packages/matplotlib/backends/backend_agg.py:256, in RendererAgg.get_text_width_height_descent(self, s, prop, ismath)
254 _api.check_in_list(["TeX", True, False], ismath=ismath)
255 if ismath == "TeX":
--> 256 return super().get_text_width_height_descent(s, prop, ismath)
258 if ismath:
259 parse = self.mathtext_parser.parse(s, self.dpi, prop)
File /usr/local/lib/python3.14/site-packages/matplotlib/backend_bases.py:589, in RendererBase.get_text_width_height_descent(self, s, prop, ismath)
585 fontsize = prop.get_size_in_points()
587 if ismath == 'TeX':
588 # todo: handle properties
--> 589 return self.get_texmanager().get_text_width_height_descent(
590 s, fontsize, renderer=self)
592 dpi = self.points_to_pixels(72)
593 if ismath:
File /usr/local/lib/python3.14/site-packages/matplotlib/texmanager.py:369, in TexManager.get_text_width_height_descent(cls, tex, fontsize, renderer)
367 if tex.strip() == '':
368 return 0, 0, 0
--> 369 dvipath = cls.make_dvi(tex, fontsize)
370 dpi_fraction = renderer.points_to_pixels(1.) if renderer else 1
371 with dviread.Dvi(dvipath, 72 * dpi_fraction) as dvi:
File /usr/local/lib/python3.14/site-packages/matplotlib/texmanager.py:301, in TexManager.make_dvi(cls, tex, fontsize)
298 with TemporaryDirectory(dir=dvipath.parent) as tmpdir:
299 Path(tmpdir, "file.tex").write_text(
300 cls._get_tex_source(tex, fontsize), encoding='utf-8')
--> 301 cls._run_checked_subprocess(
302 ["latex", "-interaction=nonstopmode", "-halt-on-error",
303 "-no-shell-escape", "file.tex"], tex, cwd=tmpdir)
304 Path(tmpdir, "file.dvi").replace(dvipath)
305 # Also move the tex source to the main cache directory, but
306 # only for backcompat.
File /usr/local/lib/python3.14/site-packages/matplotlib/texmanager.py:274, in TexManager._run_checked_subprocess(cls, command, tex, cwd)
262 raise RuntimeError(
263 '{prog} was not able to process the following string:\n'
264 '{tex!r}\n\n'
(...) 271 exc=exc.output.decode('utf-8', 'backslashreplace'))
272 ) from None
273 except (FileNotFoundError, OSError) as exc:
--> 274 raise RuntimeError(
275 f'Failed to process string with tex because {command[0]} '
276 'could not be found') from exc
277 _log.debug(report)
278 return report
RuntimeError: Failed to process string with tex because latex could not be found
<Figure size 300x600 with 2 Axes>
Each xLA feature in pyXla produces as output both visual and numerical outputs. For most features these outputs are returned as a pair.
The numerical output is the first item in the pair:
feat
{'f0_min': 70.48654206472348,
'f0_max': 17250.503688665594,
'f0_mean': 6984.475586503501,
'f0_med': 6386.739212703842,
'f0_q1': 3617.790500534753,
'f0_q3': 9706.684508771683,
'f0_sd': 4392.63164992962,
'f0_skew': 0.42039306093321,
'f0_kurt': -0.6140907651652197,
'f0_rank_min': 1,
'f0_rank_max': 100,
'f0_rank_mean': 50.5,
'f0_rank_med': 50.5,
'f0_rank_q1': 25.25,
'f0_rank_q3': 75.75,
'f0_rank_sd': 29.011491975882016,
'f0_rank_skew': 0.0,
'f0_rank_kurt': -1.2002400240024003}
The visual output is the second item in the pair:
plot
---------------------------------------------------------------------------
FileNotFoundError Traceback (most recent call last)
File /usr/local/lib/python3.14/site-packages/matplotlib/texmanager.py:258, in TexManager._run_checked_subprocess(cls, command, tex, cwd)
257 try:
--> 258 report = subprocess.check_output(
259 command, cwd=cwd if cwd is not None else cls._cache_dir,
260 stderr=subprocess.STDOUT)
261 except subprocess.CalledProcessError as exc:
File /usr/local/lib/python3.14/subprocess.py:473, in check_output(timeout, *popenargs, **kwargs)
471 kwargs['input'] = empty
--> 473 return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
474 **kwargs).stdout
File /usr/local/lib/python3.14/subprocess.py:555, in run(input, capture_output, timeout, check, *popenargs, **kwargs)
553 kwargs['stderr'] = PIPE
--> 555 with Popen(*popenargs, **kwargs) as process:
556 try:
File /usr/local/lib/python3.14/subprocess.py:1039, 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, process_group)
1036 self.stderr = io.TextIOWrapper(self.stderr,
1037 encoding=encoding, errors=errors)
-> 1039 self._execute_child(args, executable, preexec_fn, close_fds,
1040 pass_fds, cwd, env,
1041 startupinfo, creationflags, shell,
1042 p2cread, p2cwrite,
1043 c2pread, c2pwrite,
1044 errread, errwrite,
1045 restore_signals,
1046 gid, gids, uid, umask,
1047 start_new_session, process_group)
1048 except:
1049 # Cleanup if the child failed starting.
File /usr/local/lib/python3.14/subprocess.py:1990, 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, process_group)
1989 if err_filename is not None:
-> 1990 raise child_exception_type(errno_num, err_msg, err_filename)
1991 else:
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/local/lib/python3.14/site-packages/matplotlib/backend_bases.py:2257, in FigureCanvasBase.print_figure(self, filename, dpi, facecolor, edgecolor, orientation, format, bbox_inches, pad_inches, bbox_extra_artists, backend, **kwargs)
2254 # we do this instead of `self.figure.draw_without_rendering`
2255 # so that we can inject the orientation
2256 with getattr(renderer, "_draw_disabled", nullcontext)():
-> 2257 self.figure.draw(renderer)
2258 else:
2259 renderer = None
File /usr/local/lib/python3.14/site-packages/matplotlib/artist.py:94, in _finalize_rasterization.<locals>.draw_wrapper(artist, renderer, *args, **kwargs)
92 @wraps(draw)
93 def draw_wrapper(artist, renderer, *args, **kwargs):
---> 94 result = draw(artist, renderer, *args, **kwargs)
95 if renderer._rasterizing:
96 renderer.stop_rasterizing()
File /usr/local/lib/python3.14/site-packages/matplotlib/artist.py:71, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
68 if artist.get_agg_filter() is not None:
69 renderer.start_filter()
---> 71 return draw(artist, renderer)
72 finally:
73 if artist.get_agg_filter() is not None:
File /usr/local/lib/python3.14/site-packages/matplotlib/figure.py:3276, in Figure.draw(self, renderer)
3274 if self.axes and self.get_layout_engine() is not None:
3275 try:
-> 3276 self.get_layout_engine().execute(self)
3277 except ValueError:
3278 pass
File /usr/local/lib/python3.14/site-packages/matplotlib/layout_engine.py:278, in ConstrainedLayoutEngine.execute(self, fig)
275 w_pad = self._params['w_pad'] / width
276 h_pad = self._params['h_pad'] / height
--> 278 return do_constrained_layout(fig, w_pad=w_pad, h_pad=h_pad,
279 wspace=self._params['wspace'],
280 hspace=self._params['hspace'],
281 rect=self._params['rect'],
282 compress=self._compress)
File /usr/local/lib/python3.14/site-packages/matplotlib/_constrained_layout.py:116, in do_constrained_layout(fig, h_pad, w_pad, hspace, wspace, rect, compress)
106 return
108 for _ in range(2):
109 # do the algorithm twice. This has to be done because decorations
110 # change size after the first re-position (i.e. x/yticklabels get
(...) 114 # make margins for all the Axes and subfigures in the
115 # figure. Add margins for colorbars...
--> 116 make_layout_margins(layoutgrids, fig, renderer, h_pad=h_pad,
117 w_pad=w_pad, hspace=hspace, wspace=wspace)
118 make_margin_suptitles(layoutgrids, fig, renderer, h_pad=h_pad,
119 w_pad=w_pad)
121 # if a layout is such that a columns (or rows) margin has no
122 # constraints, we need to make all such instances in the grid
123 # match in margin size.
File /usr/local/lib/python3.14/site-packages/matplotlib/_constrained_layout.py:389, in make_layout_margins(layoutgrids, fig, renderer, w_pad, h_pad, hspace, wspace)
385 return
387 margin = get_margin_from_padding(ax, w_pad=w_pad, h_pad=h_pad,
388 hspace=hspace, wspace=wspace)
--> 389 pos, bbox = get_pos_and_bbox(ax, renderer)
390 # the margin is the distance between the bounding box of the Axes
391 # and its position (plus the padding from above)
392 margin['left'] += pos.x0 - bbox.x0
File /usr/local/lib/python3.14/site-packages/matplotlib/_constrained_layout.py:637, in get_pos_and_bbox(ax, renderer)
635 # pos is in panel co-ords, but we need in figure for the layout
636 pos = pos.transformed(fig.transSubfigure - fig.transFigure)
--> 637 tightbbox = martist._get_tightbbox_for_layout_only(ax, renderer)
638 if tightbbox is None:
639 bbox = pos
File /usr/local/lib/python3.14/site-packages/matplotlib/artist.py:1485, in _get_tightbbox_for_layout_only(obj, *args, **kwargs)
1479 """
1480 Matplotlib's `.Axes.get_tightbbox` and `.Axis.get_tightbbox` support a
1481 *for_layout_only* kwarg; this helper tries to use the kwarg but skips it
1482 when encountering third-party subclasses that do not support it.
1483 """
1484 try:
-> 1485 return obj.get_tightbbox(*args, **{**kwargs, "for_layout_only": True})
1486 except TypeError:
1487 return obj.get_tightbbox(*args, **kwargs)
File /usr/local/lib/python3.14/site-packages/matplotlib/axes/_base.py:4758, in _AxesBase.get_tightbbox(self, renderer, call_axes_locator, bbox_extra_artists, for_layout_only)
4756 if self.axison and axis.get_visible():
4757 if for_layout_only:
-> 4758 ba = martist._get_tightbbox_for_layout_only(axis, renderer)
4759 else:
4760 ba = axis.get_tightbbox(renderer)
File /usr/local/lib/python3.14/site-packages/matplotlib/artist.py:1485, in _get_tightbbox_for_layout_only(obj, *args, **kwargs)
1479 """
1480 Matplotlib's `.Axes.get_tightbbox` and `.Axis.get_tightbbox` support a
1481 *for_layout_only* kwarg; this helper tries to use the kwarg but skips it
1482 when encountering third-party subclasses that do not support it.
1483 """
1484 try:
-> 1485 return obj.get_tightbbox(*args, **{**kwargs, "for_layout_only": True})
1486 except TypeError:
1487 return obj.get_tightbbox(*args, **kwargs)
File /usr/local/lib/python3.14/site-packages/matplotlib/axis.py:1427, in Axis.get_tightbbox(self, renderer, for_layout_only)
1424 renderer = self.get_figure(root=True)._get_renderer()
1425 ticks_to_draw = self._update_ticks()
-> 1427 self._update_label_position(renderer)
1429 # go back to just this axis's tick labels
1430 tlb1, tlb2 = self._get_ticklabel_bboxes(ticks_to_draw, renderer)
File /usr/local/lib/python3.14/site-packages/matplotlib/axis.py:2615, in XAxis._update_label_position(self, renderer)
2611 return
2613 # get bounding boxes for this axis and any siblings
2614 # that have been set by `fig.align_xlabels()`
-> 2615 bboxes, bboxes2 = self._get_tick_boxes_siblings(renderer=renderer)
2616 x, y = self.label.get_position()
2618 if self.label_position == 'bottom':
2619 # Union with extents of the bottom spine if present, of the axes otherwise.
File /usr/local/lib/python3.14/site-packages/matplotlib/axis.py:2403, in Axis._get_tick_boxes_siblings(self, renderer)
2401 axis = ax._axis_map[name]
2402 ticks_to_draw = axis._update_ticks()
-> 2403 tlb, tlb2 = axis._get_ticklabel_bboxes(ticks_to_draw, renderer)
2404 bboxes.extend(tlb)
2405 bboxes2.extend(tlb2)
File /usr/local/lib/python3.14/site-packages/matplotlib/axis.py:1404, in Axis._get_ticklabel_bboxes(self, ticks, renderer)
1402 def _get_ticklabel_bboxes(self, ticks, renderer):
1403 """Return lists of bboxes for ticks' label1's and label2's."""
-> 1404 return ([tick.label1.get_window_extent(renderer)
1405 for tick in ticks
1406 if tick.label1.get_visible() and tick.label1.get_in_layout()],
1407 [tick.label2.get_window_extent(renderer)
1408 for tick in ticks
1409 if tick.label2.get_visible() and tick.label2.get_in_layout()])
File /usr/local/lib/python3.14/site-packages/matplotlib/text.py:1076, in Text.get_window_extent(self, renderer, dpi)
1071 raise RuntimeError(
1072 "Cannot get window extent of text w/o renderer. You likely "
1073 "want to call 'figure.draw_without_rendering()' first.")
1075 with cbook._setattr_cm(fig, dpi=dpi):
-> 1076 bbox, _, _ = self._get_layout(self._renderer)
1077 x, y = self.get_unitless_position()
1078 x, y = self.get_transform().transform((x, y))
File /usr/local/lib/python3.14/site-packages/matplotlib/text.py:465, in Text._get_layout(self, renderer)
462 break
463 if None in (min_ascent, min_descent):
464 # Fallback to font measurement.
--> 465 _, h, min_descent = _get_text_metrics_with_cache(
466 renderer, "lp", self._fontproperties,
467 ismath="TeX" if self.get_usetex() else False,
468 dpi=dpi)
469 min_ascent = h - min_descent
470 line_gap = 0
File /usr/local/lib/python3.14/site-packages/matplotlib/text.py:59, in _get_text_metrics_with_cache(renderer, text, fontprop, ismath, dpi)
52 get_text_metrics = _get_text_metrics_function(renderer)
53 # call the function to compute the metrics and return
54 #
55 # We pass a copy of the fontprop because FontProperties is both mutable and
56 # has a `__hash__` that depends on that mutable state. This is not ideal
57 # as it means the hash of an object is not stable over time which leads to
58 # very confusing behavior when used as keys in dictionaries or hashes.
---> 59 return get_text_metrics(text, fontprop.copy(), ismath, dpi)
File /usr/local/lib/python3.14/site-packages/matplotlib/text.py:125, in _get_text_metrics_function.<locals>._text_metrics(text, fontprop, ismath, dpi)
120 raise RuntimeError(
121 "Trying to get text metrics for a renderer that no longer exists. "
122 "This should never happen and is evidence of a bug elsewhere."
123 )
124 # do the actual method call we need and return the result
--> 125 return local_renderer.get_text_width_height_descent(text, fontprop, ismath)
File /usr/local/lib/python3.14/site-packages/matplotlib/backends/backend_agg.py:256, in RendererAgg.get_text_width_height_descent(self, s, prop, ismath)
254 _api.check_in_list(["TeX", True, False], ismath=ismath)
255 if ismath == "TeX":
--> 256 return super().get_text_width_height_descent(s, prop, ismath)
258 if ismath:
259 parse = self.mathtext_parser.parse(s, self.dpi, prop)
File /usr/local/lib/python3.14/site-packages/matplotlib/backend_bases.py:589, in RendererBase.get_text_width_height_descent(self, s, prop, ismath)
585 fontsize = prop.get_size_in_points()
587 if ismath == 'TeX':
588 # todo: handle properties
--> 589 return self.get_texmanager().get_text_width_height_descent(
590 s, fontsize, renderer=self)
592 dpi = self.points_to_pixels(72)
593 if ismath:
File /usr/local/lib/python3.14/site-packages/matplotlib/texmanager.py:369, in TexManager.get_text_width_height_descent(cls, tex, fontsize, renderer)
367 if tex.strip() == '':
368 return 0, 0, 0
--> 369 dvipath = cls.make_dvi(tex, fontsize)
370 dpi_fraction = renderer.points_to_pixels(1.) if renderer else 1
371 with dviread.Dvi(dvipath, 72 * dpi_fraction) as dvi:
File /usr/local/lib/python3.14/site-packages/matplotlib/texmanager.py:301, in TexManager.make_dvi(cls, tex, fontsize)
298 with TemporaryDirectory(dir=dvipath.parent) as tmpdir:
299 Path(tmpdir, "file.tex").write_text(
300 cls._get_tex_source(tex, fontsize), encoding='utf-8')
--> 301 cls._run_checked_subprocess(
302 ["latex", "-interaction=nonstopmode", "-halt-on-error",
303 "-no-shell-escape", "file.tex"], tex, cwd=tmpdir)
304 Path(tmpdir, "file.dvi").replace(dvipath)
305 # Also move the tex source to the main cache directory, but
306 # only for backcompat.
File /usr/local/lib/python3.14/site-packages/matplotlib/texmanager.py:274, in TexManager._run_checked_subprocess(cls, command, tex, cwd)
262 raise RuntimeError(
263 '{prog} was not able to process the following string:\n'
264 '{tex!r}\n\n'
(...) 271 exc=exc.output.decode('utf-8', 'backslashreplace'))
272 ) from None
273 except (FileNotFoundError, OSError) as exc:
--> 274 raise RuntimeError(
275 f'Failed to process string with tex because {command[0]} '
276 'could not be found') from exc
277 _log.debug(report)
278 return report
RuntimeError: Failed to process string with tex because latex could not be found
<Figure size 300x600 with 2 Axes>
For a complete reference of all the xLA features implemented in pyXla see the API reference.