From 3d4b1b1808e474acc57b9b441e27e84aa823b110 Mon Sep 17 00:00:00 2001
From: Martin Reinecke <martin@mpa-garching.mpg.de>
Date: Mon, 22 Jan 2018 20:50:12 +0100
Subject: [PATCH] more documentation, a few fixes

---
 docs/source/conf.py                      |  4 +-
 docs/source/index.rst                    | 10 ++-
 docs/source/start.rst                    | 96 +++++++++++++++++++++---
 nifty4/__init__.py                       | 12 ++-
 nifty4/minimization/descent_minimizer.py |  4 +-
 nifty4/plotting/plot.py                  |  6 +-
 nifty4/spaces/power_space.py             |  3 +-
 nifty4/spaces/rg_space.py                |  9 +--
 nifty4/spaces/space.py                   |  2 +-
 nifty4/utilities.py                      |  2 +-
 10 files changed, 117 insertions(+), 31 deletions(-)

diff --git a/docs/source/conf.py b/docs/source/conf.py
index 5816eb47e..694a03924 100644
--- a/docs/source/conf.py
+++ b/docs/source/conf.py
@@ -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
diff --git a/docs/source/index.rst b/docs/source/index.rst
index 536e83189..34ee9486c 100644
--- a/docs/source/index.rst
+++ b/docs/source/index.rst
@@ -1,9 +1,14 @@
 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`
diff --git a/docs/source/start.rst b/docs/source/start.rst
index e6a36f49d..3a16dbd3e 100644
--- a/docs/source/start.rst
+++ b/docs/source/start.rst
@@ -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
+............
diff --git a/nifty4/__init__.py b/nifty4/__init__.py
index fa9ee60f3..68c51314d 100644
--- a/nifty4/__init__.py
+++ b/nifty4/__init__.py
@@ -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"]
diff --git a/nifty4/minimization/descent_minimizer.py b/nifty4/minimization/descent_minimizer.py
index 922383955..a4e45b01c 100644
--- a/nifty4/minimization/descent_minimizer.py
+++ b/nifty4/minimization/descent_minimizer.py
@@ -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,
diff --git a/nifty4/plotting/plot.py b/nifty4/plotting/plot.py
index 8220bce99..75ed595cd 100644
--- a/nifty4/plotting/plot.py
+++ b/nifty4/plotting/plot.py
@@ -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):
diff --git a/nifty4/spaces/power_space.py b/nifty4/spaces/power_space.py
index 67fd8a8a3..f5b9d38a0 100644
--- a/nifty4/spaces/power_space.py
+++ b/nifty4/spaces/power_space.py
@@ -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 = {}
diff --git a/nifty4/spaces/rg_space.py b/nifty4/spaces/rg_space.py
index 1703222f3..01e3d3b6d 100644
--- a/nifty4/spaces/rg_space.py
+++ b/nifty4/spaces/rg_space.py
@@ -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).
     """
 
diff --git a/nifty4/spaces/space.py b/nifty4/spaces/space.py
index d785977c3..17171c6b0 100644
--- a/nifty4/spaces/space.py
+++ b/nifty4/spaces/space.py
@@ -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
 
diff --git a/nifty4/utilities.py b/nifty4/utilities.py
index 1383b710d..fb7b4f04e 100644
--- a/nifty4/utilities.py
+++ b/nifty4/utilities.py
@@ -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.
-- 
GitLab