From cfb1262ae394edeb6d4ea3aefcc00b452e3d5ac7 Mon Sep 17 00:00:00 2001 From: dboe <dboe@ipp.mpg.de> Date: Mon, 26 Oct 2020 13:08:43 +0100 Subject: [PATCH] added some todos to core --- tfields/__init__.py | 4 +++- tfields/core.py | 31 +++++++++++++++++++++---------- tfields/lib/decorators.py | 25 +++++++++++++++++-------- tfields/mask.py | 28 +++++++++++++++------------- 4 files changed, 56 insertions(+), 32 deletions(-) diff --git a/tfields/__init__.py b/tfields/__init__.py index 3917788..7f921e3 100644 --- a/tfields/__init__.py +++ b/tfields/__init__.py @@ -1,5 +1,7 @@ # flake8: noqa: F401 -"""Top-level package of tfields.""" +"""Top-level package of tfields. +TODO: proper documentation, also in dough. +""" __author__ = """Daniel Böckenhoff""" __email__ = "dboe@ipp.mpg.de" diff --git a/tfields/core.py b/tfields/core.py index f3fadf7..e31ea79 100644 --- a/tfields/core.py +++ b/tfields/core.py @@ -2,15 +2,18 @@ # encoding: utf-8 """ Author: Daniel Boeckenhoff -Mail: daniel.boeckenhoff@ipp.mpg.de +Mail: dboe@ipp.mpg.de core of tfields library contains numpy ndarray derived bases of the tfields package Notes: - * It could be worthwhile concidering `np.li.mixins.NDArrayOperatorsMixin ... - <https://docs.scipy.org/doc/numpy-1.15.1/reference/generated/... - ... numpy.lib.mixins.NDArrayOperatorsMixin.html>` + * It could be worthwhile concidering [np.li.mixins.NDArrayOperatorsMixin]<https:// +docs.scipy.org/doc/numpy-1.15.1/reference/generated/numpy.lib.mixins.NDArrayOperatorsMixin.html> + +TODO: + * lint the docstrings!!! + * maybe switch to numpy style for documentation since this is numpy derived. Not yet decided """ # builtin import warnings @@ -28,6 +31,7 @@ import scipy import sortedcontainers import rna +# 'local' import tfields.bases np.seterr(all="warn", over="raise") @@ -54,6 +58,10 @@ def dim(tensor): class AbstractObject(object): # pylint: disable=useless-object-inheritance """ Abstract base class for all tfields objects implementing polymorphisms + + TODO: + * Use abstract base class to define the polymorphism contract: + see https://stackoverflow.com/questions/3570796/why-use-abstract-base-classes-in-python """ def save(self, path, *args, **kwargs): @@ -583,7 +591,9 @@ class Tensors(AbstractNdarray): # pylint: disable=too-many-public-methods Set of tensors with the same basis. TODO: - all slot args should be protected -> _base + * implement units, one unit for each dimension + * implement automatic jacobian for metric calculation + * implement multidimensional cross product Args: tensors: np.ndarray or AbstractNdarray subclass @@ -611,10 +621,9 @@ class Tensors(AbstractNdarray): # pylint: disable=too-many-public-methods Initialize the Levi-Zivita Tensor - >>> matrices = tfields.Tensors( - ... [[[0, 0, 0], [0, 0, 1], [0, -1, 0]], - ... [[0, 0, -1], [0, 0, 0], [1, 0, 0]], - ... [[0, 1, 0], [-1, 0, 0], [0, 0, 0]]]) + >>> matrices = tfields.Tensors([[[0, 0, 0], [0, 0, 1], [0, -1, 0]], + ... [[0, 0, -1], [0, 0, 0], [1, 0, 0]], + ... [[0, 1, 0], [-1, 0, 0], [0, 0, 0]]]) >>> matrices.shape == (3, 3, 3) True >>> matrices.rank == 2 @@ -2103,9 +2112,11 @@ class Maps(sortedcontainers.SortedDict, AbstractObject): | List(Tuple(int, TensorFields)): | TensorFields: | Tuple(Tensors, *Fields)): - TODO: there is more + TODO: document ) + **kwargs: forwarded to SortedDict + TODO: further documentation """ def __init__(self, *args, **kwargs): diff --git a/tfields/lib/decorators.py b/tfields/lib/decorators.py index 1ff9ed1..ff39988 100644 --- a/tfields/lib/decorators.py +++ b/tfields/lib/decorators.py @@ -5,8 +5,8 @@ import time import functools -class cached_property(object): - '''Decorator for read-only properties evaluated only once within TTL period. +class cached_property(object): # pylint: disable=invalid-name + """Decorator for read-only properties evaluated only once within TTL period. It can be used to create a cached property like this:: @@ -35,7 +35,8 @@ class cached_property(object): del instance._cache[<property name>] - ''' + """ + def __init__(self, ttl=0): self.ttl = ttl @@ -69,10 +70,13 @@ def parametrized(dec): """ possibility to parametrize a decorator """ + def layer(*args, **kwargs): - def repl(f): - return dec(f, *args, **kwargs) + def repl(fun): + return dec(fun, *args, **kwargs) + return repl + return layer @@ -107,17 +111,22 @@ def once(method, arg=False): already """ + @functools.wraps(method) def decorator(self, *args, **kwargs): if getattr(self, arg): - raise RuntimeError("Argument {arg} indicates the method has been " - "run already".format(**locals())) + raise RuntimeError( + "Argument {arg} indicates the method has been " + "run already".format(**locals()) + ) value = method(self, *args, **kwargs) setattr(self, arg, True) return value + return decorator -if __name__ == '__main__': +if __name__ == "__main__": import doctest + doctest.testmod() diff --git a/tfields/mask.py b/tfields/mask.py index 4d9b602..9054780 100644 --- a/tfields/mask.py +++ b/tfields/mask.py @@ -11,16 +11,16 @@ import numpy as np import sympy -def evalf(array, cutExpression=None, coords=None): +def evalf(array, cut_expression=None, coords=None): """ - Linking sympy and numpy by retrieving a mask according to the cutExpression + Linking sympy and numpy by retrieving a mask according to the cut_expression Args: array (numpy ndarray) - cutExpression (sympy logical expression) + cut_expression (sympy logical expression) coord_sys (str): coord_sys to evalfuate the expression in. Returns: - np.array: mask which is True, where cutExpression evalfuates True. + np.array: mask which is True, where cut_expression evalfuates True. Examples: >>> import sympy >>> import numpy as np @@ -58,28 +58,30 @@ def evalf(array, cutExpression=None, coords=None): """ if isinstance(array, list): array = np.array(array) - if cutExpression is None: + if cut_expression is None: return np.full((array.shape[0]), False, dtype=bool) if len(array.shape) != 2: raise NotImplementedError("Array shape other than 2") if coords is None: if array.shape[1] == 3: - coords = sympy.symbols('x y z') + coords = sympy.symbols("x y z") else: raise ValueError("coords are None and shape is not (?, 3)") elif len(coords) != array.shape[1]: - raise ValueError("Length of coords is not {0} but {1}" - .format(array.shape[1], len(coords))) + raise ValueError( + "Length of coords is not {0} but {1}".format(array.shape[1], len(coords)) + ) - preMask = sympy.utilities.lambdify( - coords, cutExpression, - modules={'&': np.logical_and, '|': np.logical_or}) + pre_mask = sympy.utilities.lambdify( + coords, cut_expression, modules={"&": np.logical_and, "|": np.logical_or} + ) - mask = np.array([preMask(*vals) for vals in array], dtype=bool) + mask = np.array([pre_mask(*vals) for vals in array], dtype=bool) return mask -if __name__ == '__main__': # pragma: no cover +if __name__ == "__main__": # pragma: no cover import doctest + doctest.testmod() -- GitLab