Skip to content

Commit dc97008

Browse files
Holger Kohrkohr-h
Holger Kohr
authored andcommitted
WIP: improve repr by a lot
- 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
1 parent fa6e862 commit dc97008

37 files changed

+2681
-1527
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,4 +90,7 @@ target/
9090
*.ipynb
9191
.ipynb_checkpoints
9292

93+
# VS Code files
94+
.vscode/
95+
9396
# Documentation build files

odl/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ This is a brief description of the content of each submodule, see the individual
2121
* [phantom](phantom) Standardized test images. Functions for generating standardized test examples such as `shepp_logan`.
2222
* [set](set) Sets of objects. Defines the abstract class `Set` and `LinearSpace` as well as some concrete implementations such as `RealNumbers`.
2323
* [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`.
24-
* [space](space) Concrete vector spaces. Contains concrete implementations of `LinearSpace`, including `NumpyFnBase` and `ProductSpace`.
24+
* [space](space) Concrete vector spaces. Contains concrete implementations of `LinearSpace`, including `NumpyTensorSpace` and `ProductSpace`.
2525
* [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.
2626
* [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`.
2727
* [trafos](trafos) Transformations between spaces. Defines `FourierTransform` and `WaveletTransform`.

odl/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@
3838
except TypeError:
3939
pass
4040

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

4245
# Propagate names defined in` __all__` of all "core" subpackages into
4346
# the top-level namespace

odl/contrib/fom/supervised.py

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,9 @@ def mean_squared_error(data, ground_truth, mask=None, normalized=False):
2727
2828
Parameters
2929
----------
30-
data : `FnBaseVector`
30+
data : `Tensor`
3131
Input data to compare to the ground truth.
32-
ground_truth : `FnBaseVector`
32+
ground_truth : `Tensor`
3333
Reference to compare ``data`` to.
3434
mask : `array-like`, optional
3535
If given, ``data * mask`` is compared to ``ground_truth * mask``.
@@ -85,9 +85,9 @@ def mean_absolute_error(data, ground_truth, mask=None, normalized=False):
8585
8686
Parameters
8787
----------
88-
data : `FnBaseVector`
88+
data : `Tensor`
8989
Input data to compare to the ground truth.
90-
ground_truth : `FnBaseVector`
90+
ground_truth : `Tensor`
9191
Reference to compare ``data`` to.
9292
mask : `array-like`, optional
9393
If given, ``data * mask`` is compared to ``ground_truth * mask``.
@@ -137,9 +137,9 @@ def mean_value_difference(data, ground_truth, mask=None, normalized=False):
137137
138138
Parameters
139139
----------
140-
data : `FnBaseVector`
140+
data : `Tensor`
141141
Input data to compare to the ground truth.
142-
ground_truth : `FnBaseVector`
142+
ground_truth : `Tensor`
143143
Reference to compare ``data`` to.
144144
mask : `array-like`, optional
145145
If given, ``data * mask`` is compared to ``ground_truth * mask``.
@@ -198,9 +198,9 @@ def standard_deviation_difference(data, ground_truth, mask=None,
198198
199199
Parameters
200200
----------
201-
data : `FnBaseVector`
201+
data : `Tensor`
202202
Input data to compare to the ground truth.
203-
ground_truth : `FnBaseVector`
203+
ground_truth : `Tensor`
204204
Reference to compare ``data`` to.
205205
mask : `array-like`, optional
206206
If given, ``data * mask`` is compared to ``ground_truth * mask``.
@@ -268,9 +268,9 @@ def range_difference(data, ground_truth, mask=None, normalized=False):
268268
269269
Parameters
270270
----------
271-
data : `FnBaseVector`
271+
data : `Tensor`
272272
Input data to compare to the ground truth.
273-
ground_truth : `FnBaseVector`
273+
ground_truth : `Tensor`
274274
Reference to compare ``data`` to.
275275
mask : `array-like`, optional
276276
Binary mask or index array to define ROI in which FOM evaluation
@@ -336,9 +336,9 @@ def blurring(data, ground_truth, mask=None, normalized=False,
336336
337337
Parameters
338338
----------
339-
data : `FnBaseVector`
339+
data : `Tensor`
340340
Input data to compare to the ground truth.
341-
ground_truth : `FnBaseVector`
341+
ground_truth : `Tensor`
342342
Reference to compare ``data`` to.
343343
mask : `array-like`, optional
344344
Binary mask to define ROI in which FOM evaluation is performed.
@@ -406,9 +406,9 @@ def false_structures(data, ground_truth, mask=None, normalized=False,
406406
407407
Parameters
408408
----------
409-
data : `FnBaseVector`
409+
data : `Tensor`
410410
Input data to compare to the ground truth.
411-
ground_truth : `FnBaseVector`
411+
ground_truth : `Tensor`
412412
Reference to compare ``data`` to.
413413
mask : `array-like`, optional
414414
Binary mask to define ROI in which FOM evaluation is performed.
@@ -471,9 +471,9 @@ def ssim(data, ground_truth,
471471
472472
Parameters
473473
----------
474-
data : `FnBaseVector`
474+
data : `Tensor`
475475
Input data to compare to the ground truth.
476-
ground_truth : `FnBaseVector`
476+
ground_truth : `Tensor`
477477
Reference to compare ``data`` to.
478478
size : odd int
479479
Size in elements per axis of the Gaussian window that is used
@@ -536,9 +536,9 @@ def psnr(data, ground_truth, normalized=False):
536536
537537
Parameters
538538
----------
539-
data : `FnBaseVector`
539+
data : `Tensor`
540540
Input data to compare to the ground truth.
541-
ground_truth : `FnBaseVector`
541+
ground_truth : `Tensor`
542542
Reference to compare ``data`` to.
543543
normalized : bool
544544
If true, normalize ``data`` and ``ground_truth`` to have the

odl/contrib/tensorflow/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ This package contains ODL functionality related to [TensorFlow](https://www.tens
88
This allows using tensorflow neural networks as operators in ODL.
99
* `as_tensorflow_layer` in [layer.py](layer.py) wraps an ODL operator into a tensorflow layer.
1010
This allows using arbitrary ODL operators inside tensorflow neural networks.
11-
* `TensorflowSpace` in [space.py](space.py) is a `FnBase`-type space which uses tensorflow as a backend.
11+
* `TensorflowSpace` in [space.py](space.py) is a `TensorSpace`-type space which uses tensorflow as a backend.
1212

1313
## Example usage
1414

odl/contrib/theano/layer.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ def __init__(self, operator):
3737
Parameters
3838
----------
3939
operator : `Operator`
40-
The operator that should be wrapped, must map `FnBase` spaces to
41-
`FnBase` spaces.
40+
The operator that should be wrapped, must map `TensorSpace`'s to
41+
`TensorSpace`'s.
4242
4343
Examples
4444
--------

odl/deform/linearized.py

Lines changed: 56 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@
88

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

11-
from __future__ import print_function, division, absolute_import
11+
from __future__ import absolute_import, division, print_function
12+
1213
import numpy as np
1314

14-
from odl.discr import DiscreteLp, Gradient, Divergence
15+
from odl.discr import DiscreteLp, Divergence, Gradient
1516
from odl.operator import Operator, PointwiseInner
1617
from odl.space import ProductSpace
17-
from odl.util import signature_string, indent
18-
18+
from odl.util import repr_string, signature_string_parts
1919

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

@@ -146,21 +146,23 @@ def __init__(self, template, domain=None):
146146
147147
>>> space = odl.uniform_discr(0, 1, 5, interp='nearest')
148148
>>> template = space.element([0, 0, 1, 0, 0])
149-
>>> op = LinDeformFixedTempl(template)
149+
>>> op = odl.deform.LinDeformFixedTempl(template)
150150
>>> disp_field = [[0, 0, 0, -0.2, 0]]
151-
>>> print(op(disp_field))
152-
[ 0., 0., 1., 1., 0.]
151+
>>> op(disp_field)
152+
uniform_discr(0.0, 1.0, 5).element([ 0., 0., 1., 1., 0.])
153153
154154
The result depends on the chosen interpolation. With 'linear'
155155
interpolation and an offset equal to half the distance between two
156156
points, 0.1, one gets the mean of the values.
157157
158158
>>> space = odl.uniform_discr(0, 1, 5, interp='linear')
159159
>>> template = space.element([0, 0, 1, 0, 0])
160-
>>> op = LinDeformFixedTempl(template)
160+
>>> op = odl.deform.LinDeformFixedTempl(template)
161161
>>> disp_field = [[0, 0, 0, -0.1, 0]]
162-
>>> print(op(disp_field))
163-
[ 0. , 0. , 1. , 0.5, 0. ]
162+
>>> op(disp_field)
163+
uniform_discr(0.0, 1.0, 5, interp='linear').element(
164+
[ 0. , 0. , 1. , 0.5, 0. ]
165+
)
164166
"""
165167
space = getattr(template, 'space', None)
166168
if not isinstance(space, DiscreteLp):
@@ -231,11 +233,24 @@ def derivative(self, displacement):
231233
return PointwiseInner(self.domain, def_grad)
232234

233235
def __repr__(self):
234-
"""Return ``repr(self)``."""
236+
"""Return ``repr(self)``.
237+
238+
Examples
239+
--------
240+
>>> space = odl.uniform_discr(0, 1, 5)
241+
>>> template = space.element([0, 0, 1, 0, 0])
242+
>>> op = odl.deform.LinDeformFixedTempl(template)
243+
>>> op
244+
LinDeformFixedTempl(
245+
uniform_discr(0.0, 1.0, 5).element([ 0., 0., 1., 0., 0.])
246+
)
247+
"""
235248
posargs = [self.template]
236-
optargs = [('domain', self.domain, self.template.space)]
237-
inner_str = signature_string(posargs, optargs, mod='!r', sep=',\n')
238-
return '{}(\n{}\n)'.format(self.__class__.__name__, indent(inner_str))
249+
optargs = [('domain', self.domain,
250+
self.template.space.real_space.tangent_bundle)]
251+
inner_parts = signature_string_parts(posargs, optargs)
252+
return repr_string(self.__class__.__name__, inner_parts,
253+
allow_mixed_seps=False)
239254

240255

241256
class LinDeformFixedDisp(Operator):
@@ -297,21 +312,23 @@ def __init__(self, displacement, templ_space=None):
297312
298313
>>> space = odl.uniform_discr(0, 1, 5)
299314
>>> disp_field = space.tangent_bundle.element([[0, 0, 0, -0.2, 0]])
300-
>>> op = LinDeformFixedDisp(disp_field)
315+
>>> op = odl.deform.LinDeformFixedDisp(disp_field)
301316
>>> template = [0, 0, 1, 0, 0]
302-
>>> print(op([0, 0, 1, 0, 0]))
303-
[ 0., 0., 1., 1., 0.]
317+
>>> op(template)
318+
uniform_discr(0.0, 1.0, 5).element([ 0., 0., 1., 1., 0.])
304319
305320
The result depends on the chosen interpolation. With 'linear'
306321
interpolation and an offset equal to half the distance between two
307322
points, 0.1, one gets the mean of the values.
308323
309324
>>> space = odl.uniform_discr(0, 1, 5, interp='linear')
310325
>>> disp_field = space.tangent_bundle.element([[0, 0, 0, -0.1, 0]])
311-
>>> op = LinDeformFixedDisp(disp_field)
326+
>>> op = odl.deform.LinDeformFixedDisp(disp_field)
312327
>>> template = [0, 0, 1, 0, 0]
313-
>>> print(op(template))
314-
[ 0. , 0. , 1. , 0.5, 0. ]
328+
>>> op(template)
329+
uniform_discr(0.0, 1.0, 5, interp='linear').element(
330+
[ 0. , 0. , 1. , 0.5, 0. ]
331+
)
315332
"""
316333
space = getattr(displacement, 'space', None)
317334
if not isinstance(space, ProductSpace):
@@ -374,11 +391,27 @@ def adjoint(self):
374391
return jacobian_det * self.inverse
375392

376393
def __repr__(self):
377-
"""Return ``repr(self)``."""
394+
"""Return ``repr(self)``.
395+
396+
Examples
397+
--------
398+
>>> space = odl.uniform_discr(0, 1, 5)
399+
>>> disp_field = space.tangent_bundle.element([[0, 0, 0, -0.2, 0]])
400+
>>> op = odl.deform.LinDeformFixedDisp(disp_field)
401+
>>> op
402+
LinDeformFixedDisp(
403+
ProductSpace(uniform_discr(0.0, 1.0, 5), 1).element(
404+
[
405+
[ 0. , 0. , 0. , -0.2, 0. ]
406+
]
407+
)
408+
)
409+
"""
378410
posargs = [self.displacement]
379411
optargs = [('templ_space', self.domain, self.displacement.space[0])]
380-
inner_str = signature_string(posargs, optargs, mod='!r', sep=',\n')
381-
return '{}(\n{}\n)'.format(self.__class__.__name__, indent(inner_str))
412+
inner_parts = signature_string_parts(posargs, optargs)
413+
return repr_string(self.__class__.__name__, inner_parts,
414+
allow_mixed_seps=False)
382415

383416

384417
if __name__ == '__main__':

0 commit comments

Comments
 (0)