"""Module managing errors."""
from __future__ import annotations
import re
import subprocess
import sys
import scooby
from pyvista._deprecate_positional_args import _deprecate_positional_args
_cmd = """\
import pyvista; \
plotter = pyvista.Plotter(notebook=False, off_screen=True); \
plotter.add_mesh(pyvista.Sphere()); \
plotter.show(auto_close=False); \
gpu_info = plotter.render_window.ReportCapabilities(); \
print(gpu_info); \
plotter.close()\
"""
def get_gpu_info(): # numpydoc ignore=RT01
"""Get all information about the GPU."""
# an OpenGL context MUST be opened before trying to do this.
proc = subprocess.run([sys.executable, '-c', _cmd], check=False, capture_output=True)
return '' if proc.returncode else proc.stdout.decode()
class GPUInfo:
"""A class to hold GPU details."""
def __init__(self):
"""Instantiate a container for the GPU information."""
self._gpu_info = get_gpu_info()
@property
def renderer(self): # numpydoc ignore=RT01
"""GPU renderer name."""
regex = re.compile('OpenGL renderer string:(.+)\n')
try:
renderer = regex.findall(self._gpu_info)[0]
except IndexError:
msg = 'Unable to parse GPU information for the renderer.'
raise RuntimeError(msg) from None
return renderer.strip()
@property
def version(self): # numpydoc ignore=RT01
"""GPU renderer version."""
regex = re.compile('OpenGL version string:(.+)\n')
try:
version = regex.findall(self._gpu_info)[0]
except IndexError:
msg = 'Unable to parse GPU information for the version.'
raise RuntimeError(msg) from None
return version.strip()
@property
def vendor(self): # numpydoc ignore=RT01
"""GPU renderer vendor."""
regex = re.compile('OpenGL vendor string:(.+)\n')
try:
vendor = regex.findall(self._gpu_info)[0]
except IndexError:
msg = 'Unable to parse GPU information for the vendor.'
raise RuntimeError(msg) from None
return vendor.strip()
def get_info(self):
"""All GPU information as tuple pairs.
Returns
-------
tuple
Tuples of ``(key, info)``.
"""
return [
('GPU Vendor', self.vendor),
('GPU Renderer', self.renderer),
('GPU Version', self.version),
]
def _repr_html_(self):
"""HTML table representation."""
fmt = '
'
row = '| {} | {} |
\n'
for meta in self.get_info():
fmt += row.format(*meta)
fmt += '
'
return fmt
def __repr__(self):
"""Representation method."""
content = '\n'
for k, v in self.get_info():
content += f'{k:>18} : {v}\n'
content += '\n'
return content
class Report(scooby.Report):
"""Generate a PyVista software environment report.
Parameters
----------
additional : sequence[types.ModuleType], sequence[str]
List of packages or package names to add to output information.
ncol : int, default: 3
Number of package-columns in html table; only has effect if
``mode='HTML'`` or ``mode='html'``.
text_width : int, default: 80
The text width for non-HTML display modes.
sort : bool, default: False
Alphabetically sort the packages.
gpu : bool, default: True
Gather information about the GPU. Defaults to ``True`` but if
experiencing rendering issues, pass ``False`` to safely generate a
report.
Examples
--------
>>> import pyvista as pv
>>> pv.Report() # doctest:+SKIP
Date: Fri Oct 28 15:54:11 2022 MDT
OS : Linux
CPU(s) : 6
Machine : x86_64
Architecture : 64bit
RAM : 62.6 GiB
Environment : IPython
File system : ext4
GPU Vendor : NVIDIA Corporation
GPU Renderer : Quadro P2000/PCIe/SSE2
GPU Version : 4.5.0 NVIDIA 470.141.03
Python 3.8.10 (default, Jun 22 2022, 20:18:18) [GCC 9.4.0]
pyvista : 0.37.dev0
vtk : 9.1.0
numpy : 1.23.3
imageio : 2.22.0
scooby : 0.7.1.dev1+gf097dad
pooch : v1.6.0
matplotlib : 3.6.0
IPython : 7.31.0
colorcet : 3.0.1
cmocean : 2.0
scipy : 1.9.1
tqdm : 4.64.1
meshio : 5.3.4
jupyterlab : 3.4.7
"""
@_deprecate_positional_args
def __init__( # noqa: PLR0917
self,
additional=None,
ncol=3,
text_width=80,
sort=False, # noqa: FBT002
gpu=True, # noqa: FBT002
):
"""Generate a :class:`scooby.Report` instance."""
from vtkmodules.vtkRenderingCore import vtkRenderWindow # noqa: PLC0415
from pyvista.plotting.tools import check_math_text_support # noqa: PLC0415
# Mandatory packages
core = ['pyvista', 'vtk', 'numpy', 'matplotlib', 'scooby', 'pooch', 'pillow']
# Optional packages.
optional = [
'imageio',
'pyvistaqt',
'PyQt5',
'IPython',
'colorcet',
'cmocean',
'ipywidgets',
'scipy',
'tqdm',
'meshio',
'jupyterlab',
'pytest_pyvista',
'trame',
'trame_client',
'trame_server',
'trame_vtk',
'trame_vuetify',
'jupyter_server_proxy',
'nest_asyncio',
]
# Information about the GPU - catch all Exception in case there is a rendering
# bug that the user is trying to report.
if gpu:
try:
extra_meta = GPUInfo().get_info()
except Exception: # noqa: BLE001
extra_meta = [
('GPU Details', 'error'),
]
else:
extra_meta = [
('GPU Details', 'None'),
]
extra_meta.append(('Render Window', vtkRenderWindow().GetClassName()))
extra_meta.append(('MathText Support', check_math_text_support()))
scooby.Report.__init__(
self,
additional=additional,
core=core, # type: ignore[arg-type]
optional=optional, # type: ignore[arg-type]
ncol=ncol,
text_width=text_width,
sort=sort,
extra_meta=extra_meta,
)