Source code for sacc.utils

import re

from astropy.table import Column
import numpy as np
import scipy.linalg

# These null values are used in place
# of missing values.
null_values = {
    'i': -1437530437530211245,
    'f': -1.4375304375e30,
    'U': '',
}


[docs]def hide_null_values(table): """Replace None values in an astropy table with a null value, and change the column type to whatever suits the remaining data points Parameters ---------- table: astropy table Table to modify in-place """ for name, col in list(table.columns.items()): if col.dtype.kind == 'O': good_values = [x for x in col if x is not None] good_kind = np.array(good_values).dtype.kind null = null_values[good_kind] good_col = np.array([null if x is None else x for x in col]) table[name] = Column(good_col)
[docs]def remove_dict_null_values(dictionary): """Remove values in a dictionary that correspond to the null values above. Parameters ---------- dictionary: dict Dict (or subclass instance or other mapping) to modify in-place """ # will figure out the list of keys to remove deletes = [] for k, v in dictionary.items(): try: dt = np.dtype(type(v)).kind if v == null_values[dt]: deletes.append(k) except (TypeError, KeyError): continue for d in deletes: del dictionary[d]
[docs]def unique_list(seq): """ Find the unique elements in a list or other sequence while maintaining the order. (i.e., remove any duplicated elements but otherwise leave it the same) Method from: https://stackoverflow.com/questions/480214/how-do-you-remove-duplicates-from-a-list-whilst-preserving-order Parameters ---------- seq: list or sequence Any input object that can be iterated Returns ------- L: list a new list of the unique objects """ seen = set() seen_add = seen.add return [x for x in seq if not (x in seen or seen_add(x))]
[docs]class Namespace: """ This helper class implements a very simple namespace object designed to store strings with the same name as their contents as a kind of simple string enum. N = Namespace('a', 'b', 'c') assert N.a=='a' assert N['a']=='a' assert N.index('b')==1 """ def __init__(self, *strings): """ Create the object from a list of strings, which will become attributes """ self._index = {} n = 0 for s in strings: self.__dict__[s] = s self._index[s] = n n += 1 def __contains__(self, s): return hasattr(self, s) def __getitem__(self, s): return getattr(self, s) def __str__(self): return "\n".join(f"- {s}" for s in self._index) def index(self, s): return self._index[s]
[docs]def invert_spd_matrix(M, strict=True): """ Invert a symmetric positive definite matrix. SPD matrices (for example, covariance matrices) have only positive eigenvalues. Based on: https://stackoverflow.com/questions/40703042/more-efficient-way-to-invert-a-matrix-knowing-it-is-symmetric-and-positive-semi Parameters ---------- M: 2d array Matrix to invert strict: bool, default=True If True, require that the matrix is SPD. If False, use a slower algorithm that will work on other matrices Returns ------- invM: 2d array Inverse matrix """ M = np.atleast_2d(M) # In strict mode we use a method which will only work for SPD matrices, # and raise an exception otherwise. if strict: L, _ = scipy.linalg.lapack.dpotrf(M, False, False) invM, info = scipy.linalg.lapack.dpotri(L) if info: raise ValueError("Matrix is not symmetric-positive-definite") else: invM = np.triu(invM) + np.triu(invM, k=1).T # Otherwise we use the generic (and also slower) method that will # work if, due to numerical issues, the matrix is not quite SPD else: invM = np.linalg.inv(M) return invM
def camel_case_split_and_lowercase(identifier): matches = re.finditer('.+?(?:(?<=[a-z])(?=[A-Z])' '|(?<=[A-Z])(?=[A-Z][a-z])|$)', identifier) return [m.group(0).lower() for m in matches]