Commit 3d4b1b18 authored by Martin Reinecke's avatar Martin Reinecke

more documentation, a few fixes

parent 3ad3e82b
Pipeline #23918 passed with stage
in 4 minutes and 42 seconds
......@@ -201,13 +201,13 @@ html_last_updated_fmt = '%b %d, %Y'
html_domain_indices = False
# If false, no index is generated.
#html_use_index = True
html_use_index = False
# If true, the index is split into individual pages for each letter.
#html_split_index = False
# If true, links to the reST sources are added to the pages.
#html_show_sourcelink = True
html_show_sourcelink = False
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
#html_show_sphinx = True
......
NIFTy -- Numerical Information Field Theory
===========================================
**NIFTy** [1]_, "\ **N**\umerical **I**\nformation **F**\ield **T**\heor\ **y**\ ", is a versatile library designed to enable the development of signal inference algorithms that operate regardless of the underlying spatial grid and its resolution. Its object-oriented framework is written in Python, although it accesses libraries written in Cython, C++, and C for efficiency.
**NIFTy** [1]_, "\ **N**\umerical **I**\nformation **F**\ield **T**\heor\ **y**\ ", is a versatile library designed to enable the development of signal inference algorithms that operate regardless of the underlying spatial grid and its resolution.
Its object-oriented framework is written in Python, although it accesses libraries written in C++ and C for efficiency.
NIFTy offers a toolkit that abstracts discretized representations of continuous spaces, fields in these spaces, and operators acting on fields into classes. Thereby, the correct normalization of operations on fields is taken care of automatically without concerning the user. This allows for an abstract formulation and programming of inference algorithms, including those derived within information field theory. Thus, NIFTy permits its user to rapidly prototype algorithms in 1D and then apply the developed code in higher-dimensional settings of real world problems. The set of spaces on which NIFTy operates comprises point sets, *n*-dimensional regular grids, spherical spaces, their harmonic counterparts, and product spaces constructed as combinations of those.
NIFTy offers a toolkit that abstracts discretized representations of continuous spaces, fields in these spaces, and operators acting on fields into classes.
Thereby, the correct normalization of operations on fields is taken care of automatically without concerning the user.
This allows for an abstract formulation and programming of inference algorithms, including those derived within information field theory.
Thus, NIFTy permits its user to rapidly prototype algorithms in 1D and then apply the developed code in higher-dimensional settings of real world problems.
The set of spaces on which NIFTy operates comprises point sets, *n*-dimensional regular grids, spherical spaces, their harmonic counterparts, and product spaces constructed as combinations of those.
References
----------
......@@ -27,6 +32,5 @@ Contents
Indices and tables
..................
* :ref:`genindex`
* :any:`Module Index <mod/modules>`
* :ref:`search`
......@@ -10,39 +10,76 @@ NIFTy4 Tutorial
.. automodule:: nifty4
NIFTy4 enables the programming of grid and resolution independent algorithms. In particular for signal inference algorithms, where a continuous signal field is to be recovered, this freedom is desirable. This is achieved with an object-oriented infrastructure that comprises, among others, abstract classes for :ref:`Spaces <spaces>`, :ref:`Fields <fields>`, and :ref:`Operators <operators>`. All those are covered in this tutorial.
NIFTy4 enables the programming of grid and resolution independent algorithms.
In particular for signal inference algorithms, where a continuous signal field is to be recovered, this freedom is desirable.
It is achieved with an object-oriented infrastructure that comprises, among others, abstract classes for :ref:`Spaces <spaces>`, :ref:`Fields <fields>`, and :ref:`Operators <operators>`.
All those are covered in this tutorial.
You should be able to import NIFTy4 like this after a successful `installation <install.html>`_.
>>> import nifty4 as ift
.. _domainobjects:
DomainObjects
.............
One of the fundamental building blocks of the NIFTy4 framework is the /domain/.
Its required capabilities are expressed by the abstract :py:class:`DomainObject` class.
A domain must be able to answer the following queries:
- its total number of data entries (pixels)
- the shape of the array that is supposed to hold them
- the pixel volume(s)
- the total volume
- equality/unequality to another :py:class:`DomainObject` instance
.. _spaces:
Spaces
......
Unstructured spaces
...................
There are domains (e.g. the data domain) which have no geometry associated to the individual data values.
In NIFTy4 they are represented by the :py:class:`FieldArray` class, which is dreived from
:py:class:`DomainObject` and simply returns 1.0 as the volume element for every pixel and the total
number of pixels as the total volume.
The very foundation of NIFTy4's framework are spaces, all of which are derived from the :py:class:`DomainObject` class.
A space can be either unstructured or live on a geometrical manifold; the former case is supported by objects of type :py:class:`FieldArray`, while the latter must be derived from :py:class:`Space` (both of which are in turn derived from :py:class:`DomainObject`).
Structured Spaces
.................
All domains defined on a geometrical manifold are derived from :py:class:`Space` (which is in turn derived from :py:class:`DomainObject`).
In addition to the capabilities of :py:class:`DomainObject`, :py:class:`Space` offers the following functionality:
- a :py:attr:`harmonic` property
- (iff the space is harmonic) some methods concerned with Gaussian convolution and the absolute distances of the individual grid cells from the origin
Examples for structured spaces are
- :py:class:`RGSpace` (an equidistant Cartesian grid with a user-definable number of dimensions),
- :py:class:`GLSpace` (a Gauss-Legendre grid on the sphere), and
- :py:class:`LMSpace` (a grid storing spherical harmonic coefficients).
Among these, :py:class:`RGSpace` can be harmonic or not (depending on constructor arguments), :py:class:`GLSpace` is a pure position space (i.e. nonharmonic), and :py:class:`LMSpace` is always harmonic.
Domains
-------
Full domains
............
A field can live on a single space, but it can also live on a product of spaces (or no space at all, in which case it is a scalar).
The set of spaces on which a field lives is a called a _domain_ in NIFTy terminology; it is described by a :py:class:`DomainTuple` object.
The tuple of spaces on which a field lives is a called a *domain* in NIFTy terminology; it is described by a :py:class:`DomainTuple` object.
A :py:class:`DomainTuple` object can be constructed from
- a single instance of anything derived from :py:class:`DomainTuple`
- a tuple of such instances (possibly empty)
- another :py:class:`DomainTuple` object
.. _fields:
Fields
------
......
A field object is specified by
A :py:class:`Field` object consists of the following components:
- a domain in form of a :py:class:`DomainTuple` object
- a data type (e.g. numpy.float64)
......@@ -52,6 +89,41 @@ Fields support arithmetic operations, contractions, etc.
.. _operators:
Operators
---------
Linear Operators
................
A linear operator (represented by NIFTy4's abstract :py:class:`LinearOperator` class) can be interpreted as an (implicitly defined) matrix.
It can be applied to :py:class:`Field` instances, resulting in other :py:class:`Field` instances that potentially live on other domains.
There are four basic ways of applying an operator :math:`A` to a field :math:`f`:
- direct multiplication: :math:`A\cdot f`
- adjoint multiplication: :math:`A^\dagger \cdot f`
- inverse multiplication: :math:`A^{-1}\cdot f`
- adjoint inverse multiplication: :math:`(A^\dagger)^{-1}\cdot f`
(For linear operators, inverse adjoint multiplication and adjoint inverse multiplication are equivalent.)
Operator classes defined in NIFTy may implement an arbitrary subset of these four operations.
If needed, the set of supported operations can be enhanced by iterative inversion methods;
for example, an operator defining direct and adjoint multiplication, could be enhanced to support the complete set by this method.
There are two domains associated with a :py:class:`LinearOperator`: a *domain* and a *target*.
Direct multiplication and adjoint inverse multiplication transform a field living on the operator's *domain* to one living on the operator's *target*, whereas adjoint multiplication and inverse multiplication transform from *target* to *domain*.
Operators with identical domain and target can be derived from :py:class:`EndomorphicOperator`;
typical examples for this category are the :py:class:`ScalingOperator`, which simply multiplies its input by a scalar value and :py:class:`DiagonalOperator`, which multiplies every value of its input field with potentially different values.
Nifty4 allows simple and intuitive construction of combined operators.
As an example, if :math:`A`, :math:`B` and :math:`C` are of type :py:class:`LinearOperator` and :math:`f_1` and :math:`f_2` are fields, writing::
X = A*B.inverse*A.adjoint + C
f2 = X(f1)
will perform the operation suggested intuitively by the notation, checking domain compatibility while building the composed operator.
.. _minimization:
Minimization
............
......@@ -3,7 +3,6 @@ from .version import __version__
from . import dobj
from .domain_object import DomainObject
from .domain_tuple import DomainTuple
from .spaces.field_array import FieldArray
from .spaces.space import Space
......@@ -14,6 +13,8 @@ from .spaces.gl_space import GLSpace
from .spaces.dof_space import DOFSpace
from .spaces.power_space import PowerSpace
from .domain_tuple import DomainTuple
from .operators.linear_operator import LinearOperator
from .operators.endomorphic_operator import EndomorphicOperator
from .operators.scaling_operator import ScalingOperator
......@@ -50,3 +51,12 @@ from .minimization.line_energy import LineEnergy
from .sugar import *
from .plotting.plot import plot
from . import library
__all__= ["DomainObject", "FieldArray", "Space", "RGSpace", "LMSpace",
"HPSpace", "GLSpace", "DOFSpace", "PowerSpace", "DomainTuple",
"LinearOperator", "EndomorphicOperator", "Scalingperator",
"DiagonalOperator", "FFTOperator", "FFTSmoothingOperator",
"DirectSmoothingOperator", "ResponseOperator", "LaplaceOperator",
"PowerProjectionOperator", "InversionEnabler",
"Field", "sqrt", "exp", "log",
"Prober", "DiagonalProberMixin", "TraceProberMixin"]
......@@ -61,8 +61,8 @@ class DescentMinimizer(Minimizer):
status : integer
Can be controller.CONVERGED or controller.ERROR
Note
----
Notes
-----
The minimization is stopped if
* the controller returns controller.CONVERGED or controller.ERROR,
* a perfectly flat point is reached,
......
......@@ -218,7 +218,8 @@ def plot(f, **kwargs):
ycoord = dobj.to_global_data(fld.val)
plt.plot(xcoord, ycoord,label=label[i])
_limit_xy(**kwargs)
plt.legend()
if label != ([None]*len(f)):
plt.legend()
_makeplot(kwargs.get("name"))
return
elif len(dom.shape) == 2:
......@@ -250,7 +251,8 @@ def plot(f, **kwargs):
ycoord = dobj.to_global_data(fld.val)
plt.plot(xcoord, ycoord, label=label[i])
_limit_xy(**kwargs)
plt.legend()
if label != ([None]*len(f)):
plt.legend()
_makeplot(kwargs.get("name"))
return
elif isinstance(dom, HPSpace):
......
......@@ -36,14 +36,13 @@ class PowerSpace(Space):
There will be as many bins as there are distinct k-vector lengths
in the harmonic partner space.
The "binbounds" property of the PowerSpace will also be None.
else:
the bin bounds requested for this PowerSpace. The array
must be sorted and strictly ascending. The first entry is the right
boundary of the first bin, and the last entry is the left boundary
of the last bin, i.e. thee will be len(binbounds)+1 bins in total,
with the first and last bins reaching to -+infinity, respectively.
(default : None)
(default : None)
"""
_powerIndexCache = {}
......
......@@ -36,12 +36,11 @@ class RGSpace(Space):
Distance between two grid points along each axis
(default: None).
If distances==None:
if harmonic==True, all distances will be set to 1
if harmonic==False, the distance along each axis will be
set to the inverse of the number of points along that
axis.
if harmonic==True, all distances will be set to 1
if harmonic==False, the distance along each axis will be
set to the inverse of the number of points along that axis.
harmonic : bool, *optional*
Whether the space represents a grid in position or harmonic space.
Whether the space represents a grid in position or harmonic space.
(default: False).
"""
......
......@@ -43,7 +43,7 @@ class Space(DomainObject):
Returns
-------
Field
An array containing the k vector lengths
An array containing the k vector lengths
"""
raise NotImplementedError
......
......@@ -34,7 +34,7 @@ def get_slice_list(shape, axes):
axes: tuple
Axes which should not be iterated over.
Yields
Returns
-------
list
The next list of indices and/or slice objects for each dimension.
......
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