Commit db0bba33 authored by Martin Reinecke's avatar Martin Reinecke
Browse files

improve docs

parent 871a3b20
Pipeline #25360 passed with stages
in 5 minutes and 54 seconds
...@@ -44,6 +44,11 @@ class Field(object): ...@@ -44,6 +44,11 @@ class Field(object):
dtype : type dtype : type
A numpy.type. Most common are float and complex. A numpy.type. Most common are float and complex.
Notes
-----
If possible, do not invoke the constructor directly, but use one of the
many convenience functions for Field conatruction!
""" """
def __init__(self, domain=None, val=None, dtype=None, copy=False, def __init__(self, domain=None, val=None, dtype=None, copy=False,
...@@ -150,17 +155,68 @@ class Field(object): ...@@ -150,17 +155,68 @@ class Field(object):
return Field.empty(field._domain, dtype) return Field.empty(field._domain, dtype)
@staticmethod @staticmethod
def from_global_data(domain, dobject): def from_global_data(domain, arr):
return Field(domain, dobj.from_global_data(dobject)) """Returns a Field constructed from `domain` and `arr`.
Parameters
----------
domain : DomainTuple, tuple of Domain, or Domain
the domain of the new Field
arr : numpy.ndarray
The data content to be used for the new Field.
Its shape must match the shape of `domain`.
If MPI is active, the contents of `arr` must be the same on all
MPI tasks.
"""
return Field(domain, dobj.from_global_data(arr))
def to_global_data(self): def to_global_data(self):
"""Returns an array containing the full data of the field.
Returns
-------
numpy.ndarray : array containing all field entries.
Its shape is identical to `self.shape`.
Notes
-----
Do not write to the returned array! Depending on whether MPI is
active or not, this may or may not change the field's data content.
"""
return dobj.to_global_data(self._val) return dobj.to_global_data(self._val)
@property @property
def local_data(self): def local_data(self):
"""numpy.ndarray : locally residing field data
Returns a handle to the part of the array data residing on the local
task (or to the entore array if MPI is not active).
Notes
-----
If the field is not locked, the array data can be modified.
Use with care!
"""
return dobj.local_data(self._val) return dobj.local_data(self._val)
def cast_domain(self, new_domain): def cast_domain(self, new_domain):
"""Returns a field with the same data, but a different domain
Parameters
----------
new_domain : Domain, tuple of Domain, or DomainTuple
The domain for the returned field. Must be shape-compatible to
`self`.
Returns
-------
Field
Field living on `new_domain`, but with the same data as `self`.
Notes
-----
No copy is made. If needed, use an additional copy() invocation.
"""
return Field(new_domain, self._val) return Field(new_domain, self._val)
@staticmethod @staticmethod
...@@ -189,20 +245,17 @@ class Field(object): ...@@ -189,20 +245,17 @@ class Field(object):
Parameters Parameters
---------- ----------
random_type : str random_type : 'pm1', 'normal', or 'uniform'
'pm1', 'normal', 'uniform' are the supported arguments for this The random distribution to use.
method.
domain : DomainTuple domain : DomainTuple
The domain of the output random field The domain of the output random field
dtype : type dtype : type
The datatype of the output random field The datatype of the output random field
Returns Returns
------- -------
Field Field
The output object. The newly created Field.
""" """
domain = DomainTuple.make(domain) domain = DomainTuple.make(domain)
return Field(domain=domain, return Field(domain=domain,
...@@ -210,65 +263,80 @@ class Field(object): ...@@ -210,65 +263,80 @@ class Field(object):
shape=domain.shape, **kwargs)) shape=domain.shape, **kwargs))
def fill(self, fill_value): def fill(self, fill_value):
"""Fill `self` uniformly with `fill_value`
Parameters
----------
fill_value: float or complex or int
The value to fill the field with.
"""
self._val.fill(fill_value) self._val.fill(fill_value)
def lock(self): def lock(self):
"""Write-protect the data content of `self`.
After this call, it will no longer be possible to change the data
entries of `self`. This is convenient if, for example, a
DiagonalOperator wants to ensure that its diagonal cannot be modified
inadvertently, without making copies.
Notes
-----
This will not only prohibit modifications to the entries of `self`, but
also to the entries of any other Field or numpy array pointing to the
same data. If an unlocked instance is needed, use copy().
The fact that there is no `unlock()` method is deliberate.
"""
dobj.lock(self._val) dobj.lock(self._val)
return self return self
@property @property
def locked(self): def locked(self):
"""bool : True iff the field's data content has been locked"""
return dobj.locked(self._val) return dobj.locked(self._val)
@property @property
def val(self): def val(self):
""" Returns the data object associated with this Field. """dobj.data_object : the data object storing the field's entries
No copy is made.
Notes
-----
This property is intended for low-level, internal use only. Do not use
from outside of NIFTy's core; there should be better alternatives.
""" """
return self._val return self._val
@property @property
def dtype(self): def dtype(self):
"""type : the data type of the field's entries"""
return self._val.dtype return self._val.dtype
@property @property
def domain(self): def domain(self):
"""DomainTuple : the field's domain"""
return self._domain return self._domain
@property @property
def shape(self): def shape(self):
""" Returns the total shape of the Field's data array. """tuple of int : the concatenated shapes of all sub-domains"""
Returns
-------
tuple of int
the dimensions of the spaces in domain.
"""
return self._domain.shape return self._domain.shape
@property @property
def size(self): def size(self):
""" Returns the total number of pixel-dimensions the field has. """int : total number of pixels in the field"""
Effectively, all values from shape are multiplied.
Returns
-------
int
the dimension of the Field.
"""
return self._domain.size return self._domain.size
@property @property
def real(self): def real(self):
""" The real part of the field (data is not copied).""" """Field : The real part of the field"""
if not np.issubdtype(self.dtype, np.complexfloating): if not np.issubdtype(self.dtype, np.complexfloating):
return self return self
return Field(self._domain, self.val.real) return Field(self._domain, self.val.real)
@property @property
def imag(self): def imag(self):
""" The imaginary part of the field (data is not copied).""" """Field : The imaginary part of the field"""
if not np.issubdtype(self.dtype, np.complexfloating): if not np.issubdtype(self.dtype, np.complexfloating):
raise ValueError(".imag called on a non-complex Field") raise ValueError(".imag called on a non-complex Field")
return Field(self._domain, self.val.imag) return Field(self._domain, self.val.imag)
...@@ -277,11 +345,12 @@ class Field(object): ...@@ -277,11 +345,12 @@ class Field(object):
""" Returns a full copy of the Field. """ Returns a full copy of the Field.
The returned object will be an identical copy of the original Field. The returned object will be an identical copy of the original Field.
The copy will be writeable, even if `self` was locked.
Returns Returns
------- -------
Field Field
An identical copy of 'self'. An identical, but unlocked copy of 'self'.
""" """
return Field(val=self, copy=True) return Field(val=self, copy=True)
...@@ -294,13 +363,25 @@ class Field(object): ...@@ -294,13 +363,25 @@ class Field(object):
Returns Returns
------- -------
Field Field
A read-only version of 'self'. A read-only version of `self`.
""" """
if self.locked: return self if self.locked else Field(val=self, copy=True, locked=True)
return self
return Field(val=self, copy=True, locked=True)
def scalar_weight(self, spaces=None): def scalar_weight(self, spaces=None):
"""Returns the uniform volume element for a sub-domain of `self`.
Parameters
----------
spaces : int, tuple of int or None
indices of the sub-domains of the field's domain to be considered.
If `None`, the entire domain is used.
Returns
-------
float or None
if the requested sub-domain has a uniform volume element, it is
returned. Otherwise, `None` is returned.
"""
if np.isscalar(spaces): if np.isscalar(spaces):
return self._domain[spaces].scalar_dvol return self._domain[spaces].scalar_dvol
...@@ -315,6 +396,19 @@ class Field(object): ...@@ -315,6 +396,19 @@ class Field(object):
return res return res
def total_volume(self, spaces=None): def total_volume(self, spaces=None):
"""Returns the total volume of a sub-domain of `self`.
Parameters
----------
spaces : int, tuple of int or None
indices of the sub-domains of the field's domain to be considered.
If `None`, the entire domain is used.
Returns
-------
float
the total volume of the requested sub-domain.
"""
if np.isscalar(spaces): if np.isscalar(spaces):
return self._domain[spaces].total_volume return self._domain[spaces].total_volume
...@@ -333,8 +427,9 @@ class Field(object): ...@@ -333,8 +427,9 @@ class Field(object):
power : number power : number
The pixels get weighted with the volume-factor**power. The pixels get weighted with the volume-factor**power.
spaces : int or tuple of int spaces : None, int or tuple of int
Determines on which subspace the operation takes place. Determines on which sub-domain the operation takes place.
If None, the entire domain is used.
out : Field or None out : Field or None
if not None, the result is returned in a new Field if not None, the result is returned in a new Field
...@@ -375,7 +470,7 @@ class Field(object): ...@@ -375,7 +470,7 @@ class Field(object):
return out return out
def vdot(self, x=None, spaces=None): def vdot(self, x=None, spaces=None):
""" Computes the volume-factor-aware dot product of 'self' with x. """ Computes the dot product of 'self' with x.
Parameters Parameters
---------- ----------
......
Markdown is supported
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