Source code for apsbits.utils.helper_functions

"""
Generic utility helper functions
================================

.. autosummary::
    ~register_bluesky_magics
    ~running_in_queueserver
    ~debug_python
    ~mpl_setup
    ~is_notebook
"""

import logging
import os

import matplotlib as mpl
import matplotlib.pyplot as plt
from bluesky.magics import BlueskyMagics
from IPython import get_ipython

from apsbits.utils.config_loaders import get_config

logger = logging.getLogger(__name__)
logger.bsdev(__file__)


[docs] def register_bluesky_magics() -> None: """Register Bluesky IPython magics.""" try: ip = get_ipython() if ip is not None: ip.register_magics(BlueskyMagics) logger.info("Registered Bluesky IPython magics") except Exception as e: logger.warning("Could not register Bluesky IPython magics: %s", e)
[docs] def running_in_queueserver() -> bool: """ Check if we are running in a Bluesky queueserver. Returns: True if running in a queueserver, False otherwise. """ qs_key = "QS_CONFIG_YML" return os.environ.get(qs_key) is not None
[docs] def get_xmode_level() -> str: """ Get the current XMode debug level. Returns: The current XMode debug level. """ iconfig = get_config() xmode_level: str = iconfig.get("XMODE_DEBUG_LEVEL", "Plain") return xmode_level
[docs] def debug_python(xmode_level: str = "Plain") -> None: """ Enable detailed debugging for Python exceptions in the IPython environment. This function adjusts the xmode settings for exception tracebacks based on the provided xmode_level argument. Args: xmode_level (str): The level of detail for exception tracebacks. Defaults to "Minimal". """ ipython = get_ipython() if ipython is not None: xmode_level: str = get_xmode_level() ipython.run_line_magic("xmode", xmode_level) print("\nEnd of IPython settings\n") logger.bsdev("xmode exception level: '%s'", xmode_level)
[docs] def is_notebook() -> bool: """ Detect if the current environment is a Jupyter Notebook. Returns: bool: True if running in a notebook (Jupyter notebook or qtconsole), False otherwise. """ try: shell: str = get_ipython().__class__.__name__ if shell == "ZMQInteractiveShell": return True # Jupyter notebook or qtconsole elif shell == "TerminalInteractiveShell": return False # Terminal running IPython else: return False # Other type except NameError: return False # Standard Python interpreter
[docs] def mpl_setup() -> None: """ Configure the Matplotlib backend based on the current environment. For non-queueserver and non-notebook environments, attempts to use the 'qtAgg' backend. If 'qtAgg' is not available due to missing dependencies, falls back to the 'Agg' backend. Returns: None """ if not running_in_queueserver(): if not is_notebook(): try: mpl.use("qtAgg") plt.ion() logger.bsdev("Using qtAgg backend for matplotlib.") except Exception as exc: logger.error( "qtAgg backend is not available, falling back to Agg backend. \ Error: %s", exc, ) mpl.use("Agg")