Commit cfb1262a authored by dboe's avatar dboe
Browse files

added some todos to core

parent a6984734
Pipeline #85094 passed with stages
in 1 minute and 5 seconds
# flake8: noqa: F401 # flake8: noqa: F401
"""Top-level package of tfields.""" """Top-level package of tfields.
TODO: proper documentation, also in dough.
"""
__author__ = """Daniel Böckenhoff""" __author__ = """Daniel Böckenhoff"""
__email__ = "dboe@ipp.mpg.de" __email__ = "dboe@ipp.mpg.de"
......
...@@ -2,15 +2,18 @@ ...@@ -2,15 +2,18 @@
# encoding: utf-8 # encoding: utf-8
""" """
Author: Daniel Boeckenhoff Author: Daniel Boeckenhoff
Mail: daniel.boeckenhoff@ipp.mpg.de Mail: dboe@ipp.mpg.de
core of tfields library core of tfields library
contains numpy ndarray derived bases of the tfields package contains numpy ndarray derived bases of the tfields package
Notes: Notes:
* It could be worthwhile concidering `np.li.mixins.NDArrayOperatorsMixin ... * It could be worthwhile concidering [np.li.mixins.NDArrayOperatorsMixin]<https://
<https://docs.scipy.org/doc/numpy-1.15.1/reference/generated/... docs.scipy.org/doc/numpy-1.15.1/reference/generated/numpy.lib.mixins.NDArrayOperatorsMixin.html>
... 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 # builtin
import warnings import warnings
...@@ -28,6 +31,7 @@ import scipy ...@@ -28,6 +31,7 @@ import scipy
import sortedcontainers import sortedcontainers
import rna import rna
# 'local'
import tfields.bases import tfields.bases
np.seterr(all="warn", over="raise") np.seterr(all="warn", over="raise")
...@@ -54,6 +58,10 @@ def dim(tensor): ...@@ -54,6 +58,10 @@ def dim(tensor):
class AbstractObject(object): # pylint: disable=useless-object-inheritance class AbstractObject(object): # pylint: disable=useless-object-inheritance
""" """
Abstract base class for all tfields objects implementing polymorphisms 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): def save(self, path, *args, **kwargs):
...@@ -583,7 +591,9 @@ class Tensors(AbstractNdarray): # pylint: disable=too-many-public-methods ...@@ -583,7 +591,9 @@ class Tensors(AbstractNdarray): # pylint: disable=too-many-public-methods
Set of tensors with the same basis. Set of tensors with the same basis.
TODO: 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: Args:
tensors: np.ndarray or AbstractNdarray subclass tensors: np.ndarray or AbstractNdarray subclass
...@@ -611,10 +621,9 @@ class Tensors(AbstractNdarray): # pylint: disable=too-many-public-methods ...@@ -611,10 +621,9 @@ class Tensors(AbstractNdarray): # pylint: disable=too-many-public-methods
Initialize the Levi-Zivita Tensor Initialize the Levi-Zivita Tensor
>>> matrices = tfields.Tensors( >>> matrices = tfields.Tensors([[[0, 0, 0], [0, 0, 1], [0, -1, 0]],
... [[[0, 0, 0], [0, 0, 1], [0, -1, 0]], ... [[0, 0, -1], [0, 0, 0], [1, 0, 0]],
... [[0, 0, -1], [0, 0, 0], [1, 0, 0]], ... [[0, 1, 0], [-1, 0, 0], [0, 0, 0]]])
... [[0, 1, 0], [-1, 0, 0], [0, 0, 0]]])
>>> matrices.shape == (3, 3, 3) >>> matrices.shape == (3, 3, 3)
True True
>>> matrices.rank == 2 >>> matrices.rank == 2
...@@ -2103,9 +2112,11 @@ class Maps(sortedcontainers.SortedDict, AbstractObject): ...@@ -2103,9 +2112,11 @@ class Maps(sortedcontainers.SortedDict, AbstractObject):
| List(Tuple(int, TensorFields)): | List(Tuple(int, TensorFields)):
| TensorFields: | TensorFields:
| Tuple(Tensors, *Fields)): | Tuple(Tensors, *Fields)):
TODO: there is more TODO: document
) )
**kwargs: forwarded to SortedDict
TODO: further documentation
""" """
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
......
...@@ -5,8 +5,8 @@ import time ...@@ -5,8 +5,8 @@ import time
import functools import functools
class cached_property(object): class cached_property(object): # pylint: disable=invalid-name
'''Decorator for read-only properties evaluated only once within TTL period. """Decorator for read-only properties evaluated only once within TTL period.
It can be used to create a cached property like this:: It can be used to create a cached property like this::
...@@ -35,7 +35,8 @@ class cached_property(object): ...@@ -35,7 +35,8 @@ class cached_property(object):
del instance._cache[<property name>] del instance._cache[<property name>]
''' """
def __init__(self, ttl=0): def __init__(self, ttl=0):
self.ttl = ttl self.ttl = ttl
...@@ -69,10 +70,13 @@ def parametrized(dec): ...@@ -69,10 +70,13 @@ def parametrized(dec):
""" """
possibility to parametrize a decorator possibility to parametrize a decorator
""" """
def layer(*args, **kwargs): def layer(*args, **kwargs):
def repl(f): def repl(fun):
return dec(f, *args, **kwargs) return dec(fun, *args, **kwargs)
return repl return repl
return layer return layer
...@@ -107,17 +111,22 @@ def once(method, arg=False): ...@@ -107,17 +111,22 @@ def once(method, arg=False):
already already
""" """
@functools.wraps(method) @functools.wraps(method)
def decorator(self, *args, **kwargs): def decorator(self, *args, **kwargs):
if getattr(self, arg): if getattr(self, arg):
raise RuntimeError("Argument {arg} indicates the method has been " raise RuntimeError(
"run already".format(**locals())) "Argument {arg} indicates the method has been "
"run already".format(**locals())
)
value = method(self, *args, **kwargs) value = method(self, *args, **kwargs)
setattr(self, arg, True) setattr(self, arg, True)
return value return value
return decorator return decorator
if __name__ == '__main__': if __name__ == "__main__":
import doctest import doctest
doctest.testmod() doctest.testmod()
...@@ -11,16 +11,16 @@ import numpy as np ...@@ -11,16 +11,16 @@ import numpy as np
import sympy 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: Args:
array (numpy ndarray) array (numpy ndarray)
cutExpression (sympy logical expression) cut_expression (sympy logical expression)
coord_sys (str): coord_sys to evalfuate the expression in. coord_sys (str): coord_sys to evalfuate the expression in.
Returns: Returns:
np.array: mask which is True, where cutExpression evalfuates True. np.array: mask which is True, where cut_expression evalfuates True.
Examples: Examples:
>>> import sympy >>> import sympy
>>> import numpy as np >>> import numpy as np
...@@ -58,28 +58,30 @@ def evalf(array, cutExpression=None, coords=None): ...@@ -58,28 +58,30 @@ def evalf(array, cutExpression=None, coords=None):
""" """
if isinstance(array, list): if isinstance(array, list):
array = np.array(array) array = np.array(array)
if cutExpression is None: if cut_expression is None:
return np.full((array.shape[0]), False, dtype=bool) return np.full((array.shape[0]), False, dtype=bool)
if len(array.shape) != 2: if len(array.shape) != 2:
raise NotImplementedError("Array shape other than 2") raise NotImplementedError("Array shape other than 2")
if coords is None: if coords is None:
if array.shape[1] == 3: if array.shape[1] == 3:
coords = sympy.symbols('x y z') coords = sympy.symbols("x y z")
else: else:
raise ValueError("coords are None and shape is not (?, 3)") raise ValueError("coords are None and shape is not (?, 3)")
elif len(coords) != array.shape[1]: elif len(coords) != array.shape[1]:
raise ValueError("Length of coords is not {0} but {1}" raise ValueError(
.format(array.shape[1], len(coords))) "Length of coords is not {0} but {1}".format(array.shape[1], len(coords))
)
preMask = sympy.utilities.lambdify( pre_mask = sympy.utilities.lambdify(
coords, cutExpression, coords, cut_expression, modules={"&": np.logical_and, "|": np.logical_or}
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 return mask
if __name__ == '__main__': # pragma: no cover if __name__ == "__main__": # pragma: no cover
import doctest import doctest
doctest.testmod() doctest.testmod()
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment