Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
ift
NIFTy
Commits
cf93d61d
Commit
cf93d61d
authored
Jan 13, 2019
by
Philipp Arras
Browse files
No whitespace after """ and further cosmetics
parent
2627a1e3
Changes
23
Hide whitespace changes
Inline
Side-by-side
nifty5/field.py
View file @
cf93d61d
...
@@ -25,7 +25,7 @@ from .domain_tuple import DomainTuple
...
@@ -25,7 +25,7 @@ from .domain_tuple import DomainTuple
class
Field
(
object
):
class
Field
(
object
):
_scalar_dom
=
DomainTuple
.
scalar_domain
()
_scalar_dom
=
DomainTuple
.
scalar_domain
()
"""
The discrete representation of a continuous field over multiple spaces.
"""The discrete representation of a continuous field over multiple spaces.
In NIFTy, Fields are used to store data arrays and carry all the needed
In NIFTy, Fields are used to store data arrays and carry all the needed
metainformation (i.e. the domain) for operators to be able to work on them.
metainformation (i.e. the domain) for operators to be able to work on them.
...
@@ -165,7 +165,7 @@ class Field(object):
...
@@ -165,7 +165,7 @@ class Field(object):
@
staticmethod
@
staticmethod
def
from_random
(
random_type
,
domain
,
dtype
=
np
.
float64
,
**
kwargs
):
def
from_random
(
random_type
,
domain
,
dtype
=
np
.
float64
,
**
kwargs
):
"""
Draws a random field with the given parameters.
"""Draws a random field with the given parameters.
Parameters
Parameters
----------
----------
...
@@ -284,7 +284,7 @@ class Field(object):
...
@@ -284,7 +284,7 @@ class Field(object):
return
res
return
res
def
weight
(
self
,
power
=
1
,
spaces
=
None
):
def
weight
(
self
,
power
=
1
,
spaces
=
None
):
"""
Weights the pixels of `self` with their invidual pixel-volume.
"""Weights the pixels of `self` with their invidual pixel-volume.
Parameters
Parameters
----------
----------
...
@@ -325,7 +325,7 @@ class Field(object):
...
@@ -325,7 +325,7 @@ class Field(object):
return
Field
.
from_local_data
(
self
.
_domain
,
aout
)
return
Field
.
from_local_data
(
self
.
_domain
,
aout
)
def
outer
(
self
,
x
):
def
outer
(
self
,
x
):
"""
Computes the outer product of 'self' with x.
"""Computes the outer product of 'self' with x.
Parameters
Parameters
----------
----------
...
@@ -342,7 +342,7 @@ class Field(object):
...
@@ -342,7 +342,7 @@ class Field(object):
return
OuterProduct
(
self
,
x
.
domain
)(
x
)
return
OuterProduct
(
self
,
x
.
domain
)(
x
)
def
vdot
(
self
,
x
=
None
,
spaces
=
None
):
def
vdot
(
self
,
x
=
None
,
spaces
=
None
):
"""
Computes the dot product of 'self' with x.
"""Computes the dot product of 'self' with x.
Parameters
Parameters
----------
----------
...
@@ -375,7 +375,7 @@ class Field(object):
...
@@ -375,7 +375,7 @@ class Field(object):
return
(
self
.
conjugate
()
*
x
).
sum
(
spaces
=
spaces
)
return
(
self
.
conjugate
()
*
x
).
sum
(
spaces
=
spaces
)
def
norm
(
self
,
ord
=
2
):
def
norm
(
self
,
ord
=
2
):
"""
Computes the L2-norm of the field values.
"""Computes the L2-norm of the field values.
Parameters
Parameters
----------
----------
...
@@ -390,7 +390,7 @@ class Field(object):
...
@@ -390,7 +390,7 @@ class Field(object):
return
dobj
.
norm
(
self
.
_val
,
ord
)
return
dobj
.
norm
(
self
.
_val
,
ord
)
def
conjugate
(
self
):
def
conjugate
(
self
):
"""
Returns the complex conjugate of the field.
"""Returns the complex conjugate of the field.
Returns
Returns
-------
-------
...
...
nifty5/library/adjust_variances.py
View file @
cf93d61d
...
@@ -30,7 +30,7 @@ def make_adjust_variances(a,
...
@@ -30,7 +30,7 @@ def make_adjust_variances(a,
samples
=
[],
samples
=
[],
scaling
=
None
,
scaling
=
None
,
ic_samp
=
None
):
ic_samp
=
None
):
"""
Creates a Hamiltonian for constant likelihood optimizations.
"""Creates a Hamiltonian for constant likelihood optimizations.
Constructs a Hamiltonian to solve constant likelihood optimizations of the
Constructs a Hamiltonian to solve constant likelihood optimizations of the
form phi = a * xi under the constraint that phi remains constant.
form phi = a * xi under the constraint that phi remains constant.
...
...
nifty5/minimization/conjugate_gradient.py
View file @
cf93d61d
...
@@ -20,7 +20,7 @@ from .minimizer import Minimizer
...
@@ -20,7 +20,7 @@ from .minimizer import Minimizer
class
ConjugateGradient
(
Minimizer
):
class
ConjugateGradient
(
Minimizer
):
"""
Implementation of the Conjugate Gradient scheme.
"""Implementation of the Conjugate Gradient scheme.
It is an iterative method for solving a linear system of equations:
It is an iterative method for solving a linear system of equations:
Ax = b
Ax = b
...
@@ -44,7 +44,7 @@ class ConjugateGradient(Minimizer):
...
@@ -44,7 +44,7 @@ class ConjugateGradient(Minimizer):
self
.
_nreset
=
nreset
self
.
_nreset
=
nreset
def
__call__
(
self
,
energy
,
preconditioner
=
None
):
def
__call__
(
self
,
energy
,
preconditioner
=
None
):
"""
Runs the conjugate gradient minimization.
"""Runs the conjugate gradient minimization.
Parameters
Parameters
----------
----------
...
...
nifty5/minimization/descent_minimizers.py
View file @
cf93d61d
...
@@ -23,7 +23,7 @@ from .minimizer import Minimizer
...
@@ -23,7 +23,7 @@ from .minimizer import Minimizer
class
DescentMinimizer
(
Minimizer
):
class
DescentMinimizer
(
Minimizer
):
"""
A base class used by gradient methods to find a local minimum.
"""A base class used by gradient methods to find a local minimum.
Descent minimization methods are used to find a local minimum of a scalar
Descent minimization methods are used to find a local minimum of a scalar
function by following a descent direction. This class implements the
function by following a descent direction. This class implements the
...
@@ -44,7 +44,7 @@ class DescentMinimizer(Minimizer):
...
@@ -44,7 +44,7 @@ class DescentMinimizer(Minimizer):
self
.
line_searcher
=
line_searcher
self
.
line_searcher
=
line_searcher
def
__call__
(
self
,
energy
):
def
__call__
(
self
,
energy
):
"""
Performs the minimization of the provided Energy functional.
"""Performs the minimization of the provided Energy functional.
Parameters
Parameters
----------
----------
...
@@ -104,7 +104,7 @@ class DescentMinimizer(Minimizer):
...
@@ -104,7 +104,7 @@ class DescentMinimizer(Minimizer):
pass
pass
def
get_descent_direction
(
self
,
energy
):
def
get_descent_direction
(
self
,
energy
):
"""
Calculates the next descent direction.
"""Calculates the next descent direction.
Parameters
Parameters
----------
----------
...
@@ -121,7 +121,7 @@ class DescentMinimizer(Minimizer):
...
@@ -121,7 +121,7 @@ class DescentMinimizer(Minimizer):
class
SteepestDescent
(
DescentMinimizer
):
class
SteepestDescent
(
DescentMinimizer
):
"""
Implementation of the steepest descent minimization scheme.
"""Implementation of the steepest descent minimization scheme.
Also known as 'gradient descent'. This algorithm simply follows the
Also known as 'gradient descent'. This algorithm simply follows the
functional's gradient for minimization.
functional's gradient for minimization.
...
@@ -132,7 +132,7 @@ class SteepestDescent(DescentMinimizer):
...
@@ -132,7 +132,7 @@ class SteepestDescent(DescentMinimizer):
class
RelaxedNewton
(
DescentMinimizer
):
class
RelaxedNewton
(
DescentMinimizer
):
"""
Calculates the descent direction according to a Newton scheme.
"""Calculates the descent direction according to a Newton scheme.
The descent direction is determined by weighting the gradient at the
The descent direction is determined by weighting the gradient at the
current parameter position with the inverse local metric.
current parameter position with the inverse local metric.
...
@@ -149,7 +149,7 @@ class RelaxedNewton(DescentMinimizer):
...
@@ -149,7 +149,7 @@ class RelaxedNewton(DescentMinimizer):
class
NewtonCG
(
DescentMinimizer
):
class
NewtonCG
(
DescentMinimizer
):
"""
Calculates the descent direction according to a Newton-CG scheme.
"""Calculates the descent direction according to a Newton-CG scheme.
Algorithm derived from SciPy sources.
Algorithm derived from SciPy sources.
"""
"""
...
...
nifty5/minimization/energy.py
View file @
cf93d61d
...
@@ -19,7 +19,7 @@ from ..utilities import NiftyMetaBase
...
@@ -19,7 +19,7 @@ from ..utilities import NiftyMetaBase
class
Energy
(
NiftyMetaBase
()):
class
Energy
(
NiftyMetaBase
()):
"""
Provides the functional used by minimization schemes.
"""Provides the functional used by minimization schemes.
The Energy object is an implementation of a scalar function including its
The Energy object is an implementation of a scalar function including its
gradient and metric at some position.
gradient and metric at some position.
...
@@ -47,7 +47,7 @@ class Energy(NiftyMetaBase()):
...
@@ -47,7 +47,7 @@ class Energy(NiftyMetaBase()):
self
.
_gradnorm
=
None
self
.
_gradnorm
=
None
def
at
(
self
,
position
):
def
at
(
self
,
position
):
"""
Returns a new Energy object, initialized at `position`.
"""Returns a new Energy object, initialized at `position`.
Parameters
Parameters
----------
----------
...
...
nifty5/minimization/line_search.py
View file @
cf93d61d
...
@@ -21,7 +21,7 @@ import numpy as np
...
@@ -21,7 +21,7 @@ import numpy as np
class
LineEnergy
(
object
):
class
LineEnergy
(
object
):
"""
Evaluates an underlying Energy along a certain line direction.
"""Evaluates an underlying Energy along a certain line direction.
Given an Energy class and a line direction, its position is parametrized by
Given an Energy class and a line direction, its position is parametrized by
a scalar step size along the descent direction relative to a zero point.
a scalar step size along the descent direction relative to a zero point.
...
@@ -60,7 +60,7 @@ class LineEnergy(object):
...
@@ -60,7 +60,7 @@ class LineEnergy(object):
self
.
_energy
=
energy
.
at
(
position
=
pos
)
self
.
_energy
=
energy
.
at
(
position
=
pos
)
def
at
(
self
,
line_position
):
def
at
(
self
,
line_position
):
"""
Returns LineEnergy at new position, memorizing the zero point.
"""Returns LineEnergy at new position, memorizing the zero point.
Parameters
Parameters
----------
----------
...
...
nifty5/minimization/minimizer.py
View file @
cf93d61d
...
@@ -19,11 +19,11 @@ from ..utilities import NiftyMetaBase
...
@@ -19,11 +19,11 @@ from ..utilities import NiftyMetaBase
class
Minimizer
(
NiftyMetaBase
()):
class
Minimizer
(
NiftyMetaBase
()):
"""
A base class used by all minimizers."""
"""A base class used by all minimizers."""
# MR FIXME: the docstring is partially ignored by Sphinx. Why?
# MR FIXME: the docstring is partially ignored by Sphinx. Why?
def
__call__
(
self
,
energy
,
preconditioner
=
None
):
def
__call__
(
self
,
energy
,
preconditioner
=
None
):
"""
Performs the minimization of the provided Energy functional.
"""Performs the minimization of the provided Energy functional.
Parameters
Parameters
----------
----------
...
...
nifty5/minimization/nonlinear_cg.py
View file @
cf93d61d
...
@@ -20,7 +20,7 @@ from .minimizer import Minimizer
...
@@ -20,7 +20,7 @@ from .minimizer import Minimizer
class
NonlinearCG
(
Minimizer
):
class
NonlinearCG
(
Minimizer
):
"""
Nonlinear Conjugate Gradient scheme according to Polak-Ribiere.
"""Nonlinear Conjugate Gradient scheme according to Polak-Ribiere.
Algorithm 5.4 from Nocedal & Wright.
Algorithm 5.4 from Nocedal & Wright.
...
...
nifty5/minimization/quadratic_energy.py
View file @
cf93d61d
...
@@ -42,7 +42,7 @@ class QuadraticEnergy(Energy):
...
@@ -42,7 +42,7 @@ class QuadraticEnergy(Energy):
return
QuadraticEnergy
(
position
,
self
.
_A
,
self
.
_b
)
return
QuadraticEnergy
(
position
,
self
.
_A
,
self
.
_b
)
def
at_with_grad
(
self
,
position
,
grad
):
def
at_with_grad
(
self
,
position
,
grad
):
"""
Specialized version of `at`, taking also a gradient.
"""Specialized version of `at`, taking also a gradient.
This custom method is meant for use within :class:ConjugateGradient`
This custom method is meant for use within :class:ConjugateGradient`
minimizers, which already have the gradient available. It saves time
minimizers, which already have the gradient available. It saves time
...
...
nifty5/multi_field.py
View file @
cf93d61d
...
@@ -142,7 +142,7 @@ class MultiField(object):
...
@@ -142,7 +142,7 @@ class MultiField(object):
for
key
in
domain
.
keys
()))
for
key
in
domain
.
keys
()))
def
norm
(
self
,
ord
=
2
):
def
norm
(
self
,
ord
=
2
):
"""
Computes the norm of the field values.
"""Computes the norm of the field values.
Parameters
Parameters
----------
----------
...
@@ -161,7 +161,7 @@ class MultiField(object):
...
@@ -161,7 +161,7 @@ class MultiField(object):
# return np.sqrt(np.abs(self.vdot(x=self)))
# return np.sqrt(np.abs(self.vdot(x=self)))
def
sum
(
self
):
def
sum
(
self
):
"""
Computes the sum all field values.
"""Computes the sum all field values.
Returns
Returns
-------
-------
...
@@ -172,7 +172,7 @@ class MultiField(object):
...
@@ -172,7 +172,7 @@ class MultiField(object):
@
property
@
property
def
size
(
self
):
def
size
(
self
):
"""
Computes the overall degrees of freedom.
"""Computes the overall degrees of freedom.
Returns
Returns
-------
-------
...
@@ -222,7 +222,7 @@ class MultiField(object):
...
@@ -222,7 +222,7 @@ class MultiField(object):
@
staticmethod
@
staticmethod
def
union
(
fields
,
domain
=
None
):
def
union
(
fields
,
domain
=
None
):
"""
Returns the union of its input fields.
"""Returns the union of its input fields.
Parameters
Parameters
----------
----------
...
...
nifty5/operators/block_diagonal_operator.py
View file @
cf93d61d
...
@@ -21,14 +21,14 @@ from .endomorphic_operator import EndomorphicOperator
...
@@ -21,14 +21,14 @@ from .endomorphic_operator import EndomorphicOperator
class
BlockDiagonalOperator
(
EndomorphicOperator
):
class
BlockDiagonalOperator
(
EndomorphicOperator
):
"""
Parameters
----------
operators : dict
Dictionary with operators domain names as keys and LinearOperators as
items.
"""
def
__init__
(
self
,
domain
,
operators
):
def
__init__
(
self
,
domain
,
operators
):
"""
Parameters
----------
operators : dict
dictionary with operators domain names as keys and
LinearOperators as items
"""
if
not
isinstance
(
domain
,
MultiDomain
):
if
not
isinstance
(
domain
,
MultiDomain
):
raise
TypeError
(
"MultiDomain expected"
)
raise
TypeError
(
"MultiDomain expected"
)
if
not
isinstance
(
operators
,
tuple
):
if
not
isinstance
(
operators
,
tuple
):
...
...
nifty5/operators/contraction_operator.py
View file @
cf93d61d
...
@@ -35,7 +35,7 @@ class ContractionOperator(LinearOperator):
...
@@ -35,7 +35,7 @@ class ContractionOperator(LinearOperator):
spaces : int or tuple of int
spaces : int or tuple of int
The elements of "domain" which are contracted.
The elements of "domain" which are contracted.
weight : int, default=0
weight : int, default=0
i
f nonzero, the fields defined on self.domain are weighted with the
I
f nonzero, the fields defined on self.domain are weighted with the
specified power.
specified power.
"""
"""
...
...
nifty5/operators/diagonal_operator.py
View file @
cf93d61d
...
@@ -24,7 +24,7 @@ from .endomorphic_operator import EndomorphicOperator
...
@@ -24,7 +24,7 @@ from .endomorphic_operator import EndomorphicOperator
class
DiagonalOperator
(
EndomorphicOperator
):
class
DiagonalOperator
(
EndomorphicOperator
):
"""
NIFTy class for diagonal operators.
"""NIFTy class for diagonal operators.
The NIFTy DiagonalOperator class is a subclass derived from the
The NIFTy DiagonalOperator class is a subclass derived from the
EndomorphicOperator. It multiplies an input field pixel-wise with its
EndomorphicOperator. It multiplies an input field pixel-wise with its
...
...
nifty5/operators/endomorphic_operator.py
View file @
cf93d61d
...
@@ -21,7 +21,7 @@ from .linear_operator import LinearOperator
...
@@ -21,7 +21,7 @@ from .linear_operator import LinearOperator
class
EndomorphicOperator
(
LinearOperator
):
class
EndomorphicOperator
(
LinearOperator
):
"""
NIFTy class for endomorphic operators.
"""NIFTy class for endomorphic operators.
The NIFTy EndomorphicOperator class is a class derived from the
The NIFTy EndomorphicOperator class is a class derived from the
LinearOperator. By definition, domain and target are the same in
LinearOperator. By definition, domain and target are the same in
...
...
nifty5/operators/exp_transform.py
View file @
cf93d61d
...
@@ -27,8 +27,7 @@ from .linear_operator import LinearOperator
...
@@ -27,8 +27,7 @@ from .linear_operator import LinearOperator
class
ExpTransform
(
LinearOperator
):
class
ExpTransform
(
LinearOperator
):
"""
"""Transforms log-space to target
Transforms log-space to target.
This operator creates a log-space subject to the degrees of freedom and
This operator creates a log-space subject to the degrees of freedom and
and its target-domain.
and its target-domain.
...
...
nifty5/operators/harmonic_operators.py
View file @
cf93d61d
...
@@ -385,9 +385,8 @@ class HarmonicTransformOperator(LinearOperator):
...
@@ -385,9 +385,8 @@ class HarmonicTransformOperator(LinearOperator):
def
HarmonicSmoothingOperator
(
domain
,
sigma
,
space
=
None
):
def
HarmonicSmoothingOperator
(
domain
,
sigma
,
space
=
None
):
""" This function returns an operator that carries out a smoothing with
"""Returns an operator that carries out a smoothing with a Gaussian kernel
a Gaussian kernel of width `sigma` on the part of `domain` given by
of width `sigma` on the part of `domain` given by `space`
`space`.
Parameters
Parameters
----------
----------
...
@@ -403,8 +402,8 @@ def HarmonicSmoothingOperator(domain, sigma, space=None):
...
@@ -403,8 +402,8 @@ def HarmonicSmoothingOperator(domain, sigma, space=None):
Notes
Notes
-----
-----
The sub-domain on which the smoothing is carried out *must* be a
The sub-domain on which the smoothing is carried out *must* be a
non-harmonic `RGSpace`.
non-harmonic `RGSpace`.
"""
"""
sigma
=
float
(
sigma
)
sigma
=
float
(
sigma
)
...
...
nifty5/operators/linear_interpolation.py
View file @
cf93d61d
...
@@ -30,8 +30,7 @@ from .linear_operator import LinearOperator
...
@@ -30,8 +30,7 @@ from .linear_operator import LinearOperator
class
LinearInterpolator
(
LinearOperator
):
class
LinearInterpolator
(
LinearOperator
):
"""
"""Multilinear interpolation for points in an RGSpace
Multilinear interpolation for points in an RGSpace
Parameters
Parameters
----------
----------
...
...
nifty5/operators/linear_operator.py
View file @
cf93d61d
...
@@ -143,7 +143,7 @@ class LinearOperator(Operator):
...
@@ -143,7 +143,7 @@ class LinearOperator(Operator):
return
self
.
apply
(
x
.
extract
(
self
.
domain
),
self
.
TIMES
)
return
self
.
apply
(
x
.
extract
(
self
.
domain
),
self
.
TIMES
)
def
apply
(
self
,
x
,
mode
):
def
apply
(
self
,
x
,
mode
):
"""
Applies the Operator to a given `x`, in a specified `mode`.
"""Applies the Operator to a given `x`, in a specified `mode`.
Parameters
Parameters
----------
----------
...
@@ -178,7 +178,7 @@ class LinearOperator(Operator):
...
@@ -178,7 +178,7 @@ class LinearOperator(Operator):
return
self
.
__matmul__
(
x
)
return
self
.
__matmul__
(
x
)
def
times
(
self
,
x
):
def
times
(
self
,
x
):
"""
Applies the Operator to a given Field.
"""Applies the Operator to a given Field.
Parameters
Parameters
----------
----------
...
@@ -223,7 +223,7 @@ class LinearOperator(Operator):
...
@@ -223,7 +223,7 @@ class LinearOperator(Operator):
return
self
.
apply
(
x
,
self
.
ADJOINT_TIMES
)
return
self
.
apply
(
x
,
self
.
ADJOINT_TIMES
)
def
adjoint_inverse_times
(
self
,
x
):
def
adjoint_inverse_times
(
self
,
x
):
"""
Applies the adjoint-inverse Operator to a given Field.
"""Applies the adjoint-inverse Operator to a given Field.
Parameters
Parameters
----------
----------
...
...
nifty5/operators/mask_operator.py
View file @
cf93d61d
...
@@ -27,16 +27,16 @@ from .linear_operator import LinearOperator
...
@@ -27,16 +27,16 @@ from .linear_operator import LinearOperator
# Possible approach: keep everything defined on `domain` distributed and only
# Possible approach: keep everything defined on `domain` distributed and only
# collect the unstructured Fields.
# collect the unstructured Fields.
class
MaskOperator
(
LinearOperator
):
class
MaskOperator
(
LinearOperator
):
def
__init__
(
self
,
mask
):
"""Implementation of a mask response
"""Implementation of a mask response
T
his operator t
akes a field, applies a mask and returns the values of
Takes a field, applies a mask and returns the values of
the field in a
the field in a
UnstructuredDomain. It can be used as response operator.
UnstructuredDomain. It can be used as response operator.
Parameters
Parameters
----------
----------
mask : Field
mask : Field
"""
"""
def
__init__
(
self
,
mask
):
if
not
isinstance
(
mask
,
Field
):
if
not
isinstance
(
mask
,
Field
):
raise
TypeError
raise
TypeError
...
...
nifty5/operators/outer_product_operator.py
View file @
cf93d61d
...
@@ -15,17 +15,11 @@
...
@@ -15,17 +15,11 @@
#
#
# NIFTy is being developed at the Max-Planck-Institut fuer Astrophysik.
# NIFTy is being developed at the Max-Planck-Institut fuer Astrophysik.
import
itertools
import
numpy
as
np
import
numpy
as
np
from
..
import
dobj
,
utilities
from
..domain_tuple
import
DomainTuple
from
..domain_tuple
import
DomainTuple
from
..domains.rg_space
import
RGSpace
from
..multi_field
import
MultiField
,
MultiDomain
from
..field
import
Field
from
..field
import
Field
from
.linear_operator
import
LinearOperator
from
.linear_operator
import
LinearOperator
import
operator
class
OuterProduct
(
LinearOperator
):
class
OuterProduct
(
LinearOperator
):
...
@@ -37,14 +31,11 @@ class OuterProduct(LinearOperator):
...
@@ -37,14 +31,11 @@ class OuterProduct(LinearOperator):
domain: DomainTuple, the domain of the input field
domain: DomainTuple, the domain of the input field
---------
---------
"""
"""
def
__init__
(
self
,
field
,
domain
):
def
__init__
(
self
,
field
,
domain
):
self
.
_domain
=
domain
self
.
_domain
=
domain
self
.
_field
=
field
self
.
_field
=
field
self
.
_target
=
DomainTuple
.
make
(
self
.
_target
=
DomainTuple
.
make
(
tuple
(
sub_d
for
sub_d
in
field
.
domain
.
_dom
+
domain
.
_dom
))
tuple
(
sub_d
for
sub_d
in
field
.
domain
.