Skip to content

Commit

Permalink
WIP: improve repr by a lot
Browse files Browse the repository at this point in the history
- add helper `_separators` to determine string
  separators that keep a `repr` string within a
  given line width
- split repr string rendering into two functions,
  one to determine the parts to be printed and
  one to compile the final string (with separators)
- `attribute_repr_string` helper to class attributes
- `element_repr_string` helper to print space
  elements
- make repr printing of product space elements more
  consistent
- improve default repr of `Operator` (now actually
  good by default, but unspecific)
- use Numpy's print options as a single point to
  configure printing
- add doctests to lots of `__repr__` methods

Further miscellaneous changes:
- fix bug of `uniform_discr_fromdiscr` ignoring dtype
- sort imports using the `isort` tool (mode `-m 4`)
- add `asweighted` to base_tensors to make weighted
  and unweighted spaces compatible in tensor operators
- remove base classes for operator and adjoint in
  favor of inner adjoint classes (less code)
- make most default operators take `domain` and `range`
  and implement the corresponding adjoints/inverses etc.
- implement `noise_array` for product spaces that
  are not power spaces
- remove the `almost_equal` test util
- improve a number of doctests (use `odl.` calls,
  better names etc.)
- make comparison of arrays in tests faster
- implement broadcasting of shapes (M, N) and (N,)
  in product spaces
- remove some remaining doc glitches, mostly `FnBase`

TODO:
- go through rest of the library
- replace `almost_equal` by `pytest.approx`
- tests for pspace broadcasting
- make `uniform_discr_fromdiscr` respect weighting
- fix failing unit tests
  • Loading branch information
Holger Kohr authored and kohr-h committed Jan 30, 2018
1 parent fa6e862 commit a5b74cc
Show file tree
Hide file tree
Showing 37 changed files with 2,680 additions and 1,526 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -90,4 +90,7 @@ target/
*.ipynb
.ipynb_checkpoints

# VS Code files
.vscode/

# Documentation build files
2 changes: 1 addition & 1 deletion odl/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ This is a brief description of the content of each submodule, see the individual
* [phantom](phantom) Standardized test images. Functions for generating standardized test examples such as `shepp_logan`.
* [set](set) Sets of objects. Defines the abstract class `Set` and `LinearSpace` as well as some concrete implementations such as `RealNumbers`.
* [solvers](solvers) Solution of equations and optimization. Contains both general solvers for problems of the form `A(x) = b` where `A` is an `Operator` as well as solvers of minimization problems. In addition, it defines the class `Functional` with several concrete implementations such as `L2Norm`.
* [space](space) Concrete vector spaces. Contains concrete implementations of `LinearSpace`, including `NumpyFnBase` and `ProductSpace`.
* [space](space) Concrete vector spaces. Contains concrete implementations of `LinearSpace`, including `NumpyTensorSpace` and `ProductSpace`.
* [test](test) Tests for the ODL package. This contains automated tests for all other ODL functionality. In general, users should not be calling anything from this submoduel.
* [tomo](tomo) Tomography. Defines the operator `RayTransform` as well as `Geometry` along with subclasses and utilities. Also defines problem dependent direct reconstruction such as `fbp_op`.
* [trafos](trafos) Transformations between spaces. Defines `FourierTransform` and `WaveletTransform`.
Expand Down
3 changes: 3 additions & 0 deletions odl/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@
except TypeError:
pass

# Set printing linewidth to 71 to allow method docstrings to not extend
# beyond 79 characters (2 times indent of 4)
np.set_printoptions(linewidth=71)

# Propagate names defined in` __all__` of all "core" subpackages into
# the top-level namespace
Expand Down
36 changes: 18 additions & 18 deletions odl/contrib/fom/supervised.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ def mean_squared_error(data, ground_truth, mask=None, normalized=False):
Parameters
----------
data : `FnBaseVector`
data : `Tensor`
Input data to compare to the ground truth.
ground_truth : `FnBaseVector`
ground_truth : `Tensor`
Reference to compare ``data`` to.
mask : `array-like`, optional
If given, ``data * mask`` is compared to ``ground_truth * mask``.
Expand Down Expand Up @@ -85,9 +85,9 @@ def mean_absolute_error(data, ground_truth, mask=None, normalized=False):
Parameters
----------
data : `FnBaseVector`
data : `Tensor`
Input data to compare to the ground truth.
ground_truth : `FnBaseVector`
ground_truth : `Tensor`
Reference to compare ``data`` to.
mask : `array-like`, optional
If given, ``data * mask`` is compared to ``ground_truth * mask``.
Expand Down Expand Up @@ -137,9 +137,9 @@ def mean_value_difference(data, ground_truth, mask=None, normalized=False):
Parameters
----------
data : `FnBaseVector`
data : `Tensor`
Input data to compare to the ground truth.
ground_truth : `FnBaseVector`
ground_truth : `Tensor`
Reference to compare ``data`` to.
mask : `array-like`, optional
If given, ``data * mask`` is compared to ``ground_truth * mask``.
Expand Down Expand Up @@ -198,9 +198,9 @@ def standard_deviation_difference(data, ground_truth, mask=None,
Parameters
----------
data : `FnBaseVector`
data : `Tensor`
Input data to compare to the ground truth.
ground_truth : `FnBaseVector`
ground_truth : `Tensor`
Reference to compare ``data`` to.
mask : `array-like`, optional
If given, ``data * mask`` is compared to ``ground_truth * mask``.
Expand Down Expand Up @@ -268,9 +268,9 @@ def range_difference(data, ground_truth, mask=None, normalized=False):
Parameters
----------
data : `FnBaseVector`
data : `Tensor`
Input data to compare to the ground truth.
ground_truth : `FnBaseVector`
ground_truth : `Tensor`
Reference to compare ``data`` to.
mask : `array-like`, optional
Binary mask or index array to define ROI in which FOM evaluation
Expand Down Expand Up @@ -336,9 +336,9 @@ def blurring(data, ground_truth, mask=None, normalized=False,
Parameters
----------
data : `FnBaseVector`
data : `Tensor`
Input data to compare to the ground truth.
ground_truth : `FnBaseVector`
ground_truth : `Tensor`
Reference to compare ``data`` to.
mask : `array-like`, optional
Binary mask to define ROI in which FOM evaluation is performed.
Expand Down Expand Up @@ -406,9 +406,9 @@ def false_structures(data, ground_truth, mask=None, normalized=False,
Parameters
----------
data : `FnBaseVector`
data : `Tensor`
Input data to compare to the ground truth.
ground_truth : `FnBaseVector`
ground_truth : `Tensor`
Reference to compare ``data`` to.
mask : `array-like`, optional
Binary mask to define ROI in which FOM evaluation is performed.
Expand Down Expand Up @@ -471,9 +471,9 @@ def ssim(data, ground_truth,
Parameters
----------
data : `FnBaseVector`
data : `Tensor`
Input data to compare to the ground truth.
ground_truth : `FnBaseVector`
ground_truth : `Tensor`
Reference to compare ``data`` to.
size : odd int
Size in elements per axis of the Gaussian window that is used
Expand Down Expand Up @@ -536,9 +536,9 @@ def psnr(data, ground_truth, normalized=False):
Parameters
----------
data : `FnBaseVector`
data : `Tensor`
Input data to compare to the ground truth.
ground_truth : `FnBaseVector`
ground_truth : `Tensor`
Reference to compare ``data`` to.
normalized : bool
If true, normalize ``data`` and ``ground_truth`` to have the
Expand Down
2 changes: 1 addition & 1 deletion odl/contrib/tensorflow/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ This package contains ODL functionality related to [TensorFlow](https://www.tens
This allows using tensorflow neural networks as operators in ODL.
* `as_tensorflow_layer` in [layer.py](layer.py) wraps an ODL operator into a tensorflow layer.
This allows using arbitrary ODL operators inside tensorflow neural networks.
* `TensorflowSpace` in [space.py](space.py) is a `FnBase`-type space which uses tensorflow as a backend.
* `TensorflowSpace` in [space.py](space.py) is a `TensorSpace`-type space which uses tensorflow as a backend.

## Example usage

Expand Down
4 changes: 2 additions & 2 deletions odl/contrib/theano/layer.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ def __init__(self, operator):
Parameters
----------
operator : `Operator`
The operator that should be wrapped, must map `FnBase` spaces to
`FnBase` spaces.
The operator that should be wrapped, must map `TensorSpace`'s to
`TensorSpace`'s.
Examples
--------
Expand Down
79 changes: 56 additions & 23 deletions odl/deform/linearized.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@

"""Operators and functions for linearized deformation."""

from __future__ import print_function, division, absolute_import
from __future__ import absolute_import, division, print_function

import numpy as np

from odl.discr import DiscreteLp, Gradient, Divergence
from odl.discr import DiscreteLp, Divergence, Gradient
from odl.operator import Operator, PointwiseInner
from odl.space import ProductSpace
from odl.util import signature_string, indent

from odl.util import repr_string, signature_string_parts

__all__ = ('LinDeformFixedTempl', 'LinDeformFixedDisp', 'linear_deform')

Expand Down Expand Up @@ -146,21 +146,23 @@ def __init__(self, template, domain=None):
>>> space = odl.uniform_discr(0, 1, 5, interp='nearest')
>>> template = space.element([0, 0, 1, 0, 0])
>>> op = LinDeformFixedTempl(template)
>>> op = odl.deform.LinDeformFixedTempl(template)
>>> disp_field = [[0, 0, 0, -0.2, 0]]
>>> print(op(disp_field))
[ 0., 0., 1., 1., 0.]
>>> op(disp_field)
uniform_discr(0.0, 1.0, 5).element([ 0., 0., 1., 1., 0.])
The result depends on the chosen interpolation. With 'linear'
interpolation and an offset equal to half the distance between two
points, 0.1, one gets the mean of the values.
>>> space = odl.uniform_discr(0, 1, 5, interp='linear')
>>> template = space.element([0, 0, 1, 0, 0])
>>> op = LinDeformFixedTempl(template)
>>> op = odl.deform.LinDeformFixedTempl(template)
>>> disp_field = [[0, 0, 0, -0.1, 0]]
>>> print(op(disp_field))
[ 0. , 0. , 1. , 0.5, 0. ]
>>> op(disp_field)
uniform_discr(0.0, 1.0, 5, interp='linear').element(
[ 0. , 0. , 1. , 0.5, 0. ]
)
"""
space = getattr(template, 'space', None)
if not isinstance(space, DiscreteLp):
Expand Down Expand Up @@ -231,11 +233,24 @@ def derivative(self, displacement):
return PointwiseInner(self.domain, def_grad)

def __repr__(self):
"""Return ``repr(self)``."""
"""Return ``repr(self)``.
Examples
--------
>>> space = odl.uniform_discr(0, 1, 5)
>>> template = space.element([0, 0, 1, 0, 0])
>>> op = odl.deform.LinDeformFixedTempl(template)
>>> op
LinDeformFixedTempl(
uniform_discr(0.0, 1.0, 5).element([ 0., 0., 1., 0., 0.])
)
"""
posargs = [self.template]
optargs = [('domain', self.domain, self.template.space)]
inner_str = signature_string(posargs, optargs, mod='!r', sep=',\n')
return '{}(\n{}\n)'.format(self.__class__.__name__, indent(inner_str))
optargs = [('domain', self.domain,
self.template.space.real_space.tangent_bundle)]
inner_parts = signature_string_parts(posargs, optargs)
return repr_string(self.__class__.__name__, inner_parts,
allow_mixed_seps=False)


class LinDeformFixedDisp(Operator):
Expand Down Expand Up @@ -297,21 +312,23 @@ def __init__(self, displacement, templ_space=None):
>>> space = odl.uniform_discr(0, 1, 5)
>>> disp_field = space.tangent_bundle.element([[0, 0, 0, -0.2, 0]])
>>> op = LinDeformFixedDisp(disp_field)
>>> op = odl.deform.LinDeformFixedDisp(disp_field)
>>> template = [0, 0, 1, 0, 0]
>>> print(op([0, 0, 1, 0, 0]))
[ 0., 0., 1., 1., 0.]
>>> op(template)
uniform_discr(0.0, 1.0, 5).element([ 0., 0., 1., 1., 0.])
The result depends on the chosen interpolation. With 'linear'
interpolation and an offset equal to half the distance between two
points, 0.1, one gets the mean of the values.
>>> space = odl.uniform_discr(0, 1, 5, interp='linear')
>>> disp_field = space.tangent_bundle.element([[0, 0, 0, -0.1, 0]])
>>> op = LinDeformFixedDisp(disp_field)
>>> op = odl.deform.LinDeformFixedDisp(disp_field)
>>> template = [0, 0, 1, 0, 0]
>>> print(op(template))
[ 0. , 0. , 1. , 0.5, 0. ]
>>> op(template)
uniform_discr(0.0, 1.0, 5, interp='linear').element(
[ 0. , 0. , 1. , 0.5, 0. ]
)
"""
space = getattr(displacement, 'space', None)
if not isinstance(space, ProductSpace):
Expand Down Expand Up @@ -374,11 +391,27 @@ def adjoint(self):
return jacobian_det * self.inverse

def __repr__(self):
"""Return ``repr(self)``."""
"""Return ``repr(self)``.
Examples
--------
>>> space = odl.uniform_discr(0, 1, 5)
>>> disp_field = space.tangent_bundle.element([[0, 0, 0, -0.2, 0]])
>>> op = odl.deform.LinDeformFixedDisp(disp_field)
>>> op
LinDeformFixedDisp(
ProductSpace(uniform_discr(0.0, 1.0, 5), 1).element(
[
[ 0. , 0. , 0. , -0.2, 0. ]
]
)
)
"""
posargs = [self.displacement]
optargs = [('templ_space', self.domain, self.displacement.space[0])]
inner_str = signature_string(posargs, optargs, mod='!r', sep=',\n')
return '{}(\n{}\n)'.format(self.__class__.__name__, indent(inner_str))
inner_parts = signature_string_parts(posargs, optargs)
return repr_string(self.__class__.__name__, inner_parts,
allow_mixed_seps=False)


if __name__ == '__main__':
Expand Down
Loading

0 comments on commit a5b74cc

Please sign in to comment.