Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion autofit/mapper/prior_model/abstract.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import copy
import functools
import inspect
import json
import logging
Expand Down Expand Up @@ -1859,7 +1860,7 @@ def order_no(self) -> str:
]
return ":".join(values)

@property
@functools.cached_property
def parameterization(self) -> str:
"""
Describes the path to each of the PriorModels, its class
Expand Down
37 changes: 30 additions & 7 deletions autofit/non_linear/live_viewer.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,33 @@
HEADLESS_BACKENDS = {"agg", "pdf", "ps", "svg", "cairo", "template"}


def _backend_can_show() -> bool:
"""Return True if the active matplotlib backend can display a window."""
_INTERACTIVE_BACKENDS = ("TkAgg", "QtAgg", "Qt5Agg", "GTK3Agg", "GTK4Agg", "WXAgg", "macosx")


def _ensure_interactive_backend() -> bool:
"""Try to switch to an interactive matplotlib backend.

The viewer subprocess inherits the parent process's backend, which is
typically ``Agg`` (the search process uses it for headless PNG
rendering). Since this subprocess exists specifically to show a
window, we try each interactive backend until one sticks. Returns
``True`` if the active backend can display a window after the
attempt.
"""
import matplotlib

backend = matplotlib.get_backend().lower()
return not any(backend.startswith(name) for name in HEADLESS_BACKENDS)
if not any(backend.startswith(name) for name in HEADLESS_BACKENDS):
return True

for candidate in _INTERACTIVE_BACKENDS:
try:
matplotlib.use(candidate)
return True
except ImportError:
continue

return False


def _install_signal_handlers(stop_event):
Expand All @@ -57,12 +78,14 @@ def _handle(signum, frame):


def run(image_path: Path, title: str) -> int:
import matplotlib
if not _ensure_interactive_backend():
import matplotlib

if not _backend_can_show():
logger.warning(
"live_viewer: matplotlib backend %r cannot display a window; "
"live visualization disabled (PNG writes to %s continue normally).",
"live_viewer: no interactive matplotlib backend found (tried %s, "
"active backend is %r). Install python3-tk or another GUI toolkit "
"to enable live visualization. PNG writes to %s continue normally.",
", ".join(_INTERACTIVE_BACKENDS),
matplotlib.get_backend(),
image_path,
)
Expand Down
Loading