Source code for physicslab.utility

"""
Utility functions.
"""


import numpy as np
import pandas as pd


[docs]def permutation_sign(array): """ Computes permutation sign of given array. Relative to ordered array, see: :math:`sgn(\\sigma) = (-1)^{\\sum_{0 \\le i<j<n}(\\sigma_i>\\sigma_j)}` .. note:: For permutation relative to another ordering, use the following identity: :math:`sgn(\\pi_1 \\circ \\pi_2) = sgn(\\pi_1)\\cdot sgn(\\pi_2)` :param array: Input array (iterable) :type array: list :return: Permutation parity sign is either (+1) or (-1) :rtype: int """ number_of_inversions = 0 n = len(array) for i in range(n): for j in range(i + 1, n): if array[i] > array[j]: number_of_inversions += 1 return (-1) ** number_of_inversions
[docs]def squarificate(iterable, filler=None): """ Reshape 1D :attr:`iterable` into squarish 2D array. | Mainly use with :meth:`physicslab.ui.plot_grid`, if the positions are arbitrary. | Example: reshape :class:`list` of 10 filenames into 3x4 array. The two new elements will be populated by :attr:`filler`. :param iterable: Source 1D iterable. :type iterable: list, numpy.ndarray :param filler: Value to pad the array with, defaults to None :type filler: object, optional :raises NotImplementedError: If :attr:`iterable` is array-like :raises ValueError: If :attr:`iterable` has more than one dimension :return: Modified array :rtype: numpy.ndarray """ if isinstance(iterable, np.ndarray): # Numpy array = iterable if isinstance(iterable, (pd.Series, pd.DataFrame)): # Pandas array = iterable.values else: # Other: list, tuple # Array constructor tries to unpack the elements to create # a multidimensional array, so the following bypasses it. array = np.empty(shape=len(iterable), dtype=object) array[:] = iterable num = array.shape if len(num) > 1: raise ValueError('Iterable attribute must be one-dimensional.') num = num[0] ncols = int(np.ceil(np.sqrt(num))) # Width. Round up to int. nrows = int(np.ceil(num / ncols)) # Height. missing = nrows * ncols - num array = np.pad(array, (0, missing), mode='constant', constant_values=filler) array = array.reshape((nrows, ncols)) return array
[docs]def get_name(df): """ Find :class:`~pandas.DataFrame` name. :param df: Input :type df: pandas.DataFrame or pandas.Series :return: Name or None if name does not exist :rtype: str or None """ return df.name if hasattr(df, 'name') else None
[docs]class _ColumnsBase: """ Abstract base class for :class:`physicslab.experiment.[Any].Columns` classes. """
[docs] @classmethod def list_all_names(cls): """ :rtype: list[str] """ return [name for name in dir(cls) if name.isupper()]