Source code for qcodes.plotting.axis_labels

"""
This file holds scaling logic for axis that is independent of plotting backend
"""
from collections import OrderedDict

import numpy as np

_UNITS_FOR_RESCALING: set[str] = {
    # SI units (without some irrelevant ones like candela)
    # 'kg' is not included because it is 'kilo' and rarely used
    "m",
    "s",
    "A",
    "K",
    "mol",
    "rad",
    "Hz",
    "N",
    "Pa",
    "J",
    "W",
    "C",
    "V",
    "F",
    "ohm",
    "Ohm",
    "Ω",
    "\N{GREEK CAPITAL LETTER OMEGA}",
    "S",
    "Wb",
    "T",
    "H",
    # non-SI units as well, for convenience
    "eV",
    "g",
}

_ENGINEERING_PREFIXES: dict[int, str] = OrderedDict(
    {
        -24: "y",
        -21: "z",
        -18: "a",
        -15: "f",
        -12: "p",
        -9: "n",
        -6: "\N{GREEK SMALL LETTER MU}",
        -3: "m",
        0: "",
        3: "k",
        6: "M",
        9: "G",
        12: "T",
        15: "P",
        18: "E",
        21: "Z",
        24: "Y",
    }
)

_THRESHOLDS: dict[float, int] = OrderedDict(
    {10 ** (scale + 3): scale for scale in _ENGINEERING_PREFIXES.keys()}
)


[docs] def find_scale_and_prefix(data: np.ndarray, unit: str) -> tuple[str, int]: """ Given a numpy array of data and a unit find the best engineering prefix and matching scale that best describes the data. The units for which unit prefixes are added can be found in ``_UNITS_FOR_RESCALING``. For all other units the prefix is an exponential scaling factor e.g. ``10^3``. If no unit is given (i.e. an empty string) no scaling is performed. Args: data: A numpy array of data. unit: The unit the data is measured in. Should not contain a prefix already. Returns: tuple of prefix and exponential scale """ maxval = np.nanmax(np.abs(data)) if unit in _UNITS_FOR_RESCALING: for threshold, scale in _THRESHOLDS.items(): if maxval == 0.0: # handle all zero data selected_scale = 0 prefix = _ENGINEERING_PREFIXES[selected_scale] break if maxval < threshold: selected_scale = scale prefix = _ENGINEERING_PREFIXES[scale] break else: # here, maxval is larger than the largest threshold largest_scale = max(list(_ENGINEERING_PREFIXES.keys())) selected_scale = largest_scale prefix = _ENGINEERING_PREFIXES[largest_scale] elif unit != "": if maxval > 0: selected_scale = 3 * (np.floor(np.floor(np.log10(maxval)) / 3)) else: selected_scale = 0 if selected_scale != 0: prefix = f"$10^{{{selected_scale:.0f}}}$ " else: prefix = "" else: prefix = "" selected_scale = 0 return prefix, selected_scale