Source code for qcodes.plotting.auto_range

"""
This file holds auto ranging logic that is independent of plotting backend
"""

import numpy as np

# turn off limiting percentiles by default
DEFAULT_PERCENTILE = (50, 50)


[docs] def auto_range_iqr( data_array: np.ndarray, cutoff_percentile: tuple[float, float] | float = DEFAULT_PERCENTILE, ) -> tuple[float, float]: """ Get the min and max range of the provided array that excludes outliers following the IQR rule. This function computes the inter-quartile-range (IQR), defined by Q3-Q1, i.e. the percentiles for 75% and 25% of the distribution. The region without outliers is defined by [Q1-1.5*IQR, Q3+1.5*IQR]. Args: data_array: Numpy array of arbitrary dimension containing the statistical data. cutoff_percentile: Percentile of data that may maximally be clipped on both sides of the distribution. If given a tuple (a,b) the percentile limits will be a and 100-b. Returns: region limits [vmin, vmax] """ if isinstance(cutoff_percentile, tuple): t = cutoff_percentile[0] b = cutoff_percentile[1] else: t = cutoff_percentile b = cutoff_percentile z = data_array.flatten() zmax = np.nanmax(z) zmin = np.nanmin(z) zrange = zmax - zmin pmin, q3, q1, pmax = np.nanpercentile(z, [b, 75, 25, 100 - t]) IQR = q3 - q1 # handle corner case of all data zero, such that IQR is zero # to counter numerical artifacts do not test IQR == 0, but IQR on its # natural scale (zrange) to be smaller than some very small number. # also test for zrange to be 0.0 to avoid division by 0. # all This is possibly to careful... if zrange == 0.0 or IQR / zrange < 1e-8: vmin = zmin vmax = zmax else: vmin = max(q1 - 1.5 * IQR, zmin) vmax = min(q3 + 1.5 * IQR, zmax) # do not clip more than cutoff_percentile: vmin = min(vmin, pmin) vmax = max(vmax, pmax) return vmin, vmax