Commit 7f0d49de authored by Martin Reinecke's avatar Martin Reinecke

Merge branch 'nifty_doc_mr' into 'NIFTy_4'

Merge Mihai's documentation enhancements

See merge request ift/NIFTy!223
parents 62254320 068485de
Pipeline #24881 passed with stages
in 6 minutes and 32 seconds
......@@ -12,12 +12,12 @@ before_script:
- sh ci/install_basics.sh
- pip install --process-dependency-links -r ci/requirements.txt
- pip3 install --process-dependency-links -r ci/requirements.txt
- pip install --user .
- pip3 install --user .
test_min:
stage: test
script:
- pip install --user .
- pip3 install --user .
- nosetests -q
- nosetests3 -q
- OMP_NUM_THREADS=1 mpiexec --allow-run-as-root -n 4 nosetests -q 2>/dev/null
......@@ -25,3 +25,13 @@ test_min:
- nosetests -q --with-coverage --cover-package=nifty4 --cover-branches --cover-erase
- >
coverage report | grep TOTAL | awk '{ print "TOTAL: "$6; }'
pages:
script:
- sh docs/generate.sh
- mv docs/build/ public/
artifacts:
paths:
- public
only:
- NIFTy_4
......@@ -4,7 +4,7 @@ NIFTy - Numerical Information Field Theory
[![coverage report](https://gitlab.mpcdf.mpg.de/ift/NIFTy/badges/NIFTy_4/coverage.svg)](https://gitlab.mpcdf.mpg.de/ift/NIFTy/commits/NIFTy_4)
**NIFTy** project homepage:
[https://www.mpa-garching.mpg.de/ift/nifty/](https://www.mpa-garching.mpg.de/ift/nifty/)
[http://ift.pages.mpcdf.de/NIFTy](http://ift.pages.mpcdf.de/NIFTy)
Summary
-------
......@@ -31,33 +31,6 @@ point sets, *n*-dimensional regular grids, spherical spaces, their
harmonic counterparts, and product spaces constructed as combinations of
those.
### Class & Feature Overview
The NIFTy library features three main classes: **Space**s that represent
certain grids, **Field**s that are defined on spaces, and **LinearOperator**s
that apply to fields.
- [Spaces](https://www.mpa-garching.mpg.de/ift/nifty/space.html)
- `RGSpace` - *n*-dimensional regular Euclidean grid
- `LMSpace` - spherical harmonics
- `GLSpace` - Gauss-Legendre grid on the 2-sphere
- `HPSpace` - [HEALPix](https://sourceforge.net/projects/healpix/)
grid on the 2-sphere
- [Fields](https://www.mpa-garching.mpg.de/ift/nifty/field.html)
- `Field` - generic class for (discretized) fields
<!-- -->
Field.conjugate Field.dim Field.norm
Field.vdot Field.weight
- [Operators](https://www.mpa-garching.mpg.de/ift/nifty/operator.html)
- `DiagonalOperator` - purely diagonal matrices in a specified
basis
- `FFTOperator` - conversion between spaces and their harmonic
counterparts
- (and more)
- (and more)
Installation
------------
......@@ -137,7 +110,7 @@ following command in the repository root:
### First Steps
For a quick start, you can browse through the [informal
introduction](https://www.mpa-garching.mpg.de/ift/nifty/start.html) or
introduction](http://ift.pages.mpcdf.de/NIFTy/start.html) or
dive into NIFTy by running one of the demonstrations, e.g.:
python demos/wiener_filter_via_curvature.py
......
parameterized
coverage
git+https://gitlab.mpcdf.mpg.de/ift/pyHealpix.git
sphinx
sphinx_rtd_theme
numpydoc
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# NIFTy4 tutorial\n",
"\n",
"Import the necessary packages:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# some voodoo to make the notebook run properly\n",
"%matplotlib inline\n",
"import nifty4 as ift\n",
"import numpy as np"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Define a space for our data"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"spc = ift.RGSpace(10) # 1D Cartesian space, contains 10 points"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"ask the space about its configuration:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print(spc)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now, create a Field with Gaussian random numbers, living on that space"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"fld = ift.Field.from_random(\"normal\",spc)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"ift.plot(fld)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now, let's do the same thing in two dimensions:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"spc = ift.RGSpace((10,10))\n",
"fld = ift.Field.from_random(\"normal\",spc)\n",
"ift.plot(fld)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now, let's do some basic arithmetics with the field"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"scrolled": true
},
"outputs": [],
"source": [
"fld += 50\n",
"fld *= -2\n",
"ift.plot(fld)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"... and smooth it."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"smooth = ift.FFTSmoothingOperator(spc,sigma=0.1)\n",
"fld_smooth = smooth(fld)\n",
"ift.plot(fld_smooth)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
" np.random.seed(43)\n",
" # Set up physical constants\n",
" # Total length of interval or volume the field lives on, e.g. in meters\n",
" L = 2.\n",
" # Typical distance over which the field is correlated (in same unit as L)\n",
" correlation_length = 0.1\n",
" # Variance of field in position space sqrt(<|s_x|^2>) (in unit of s)\n",
" field_variance = 2.\n",
" # Smoothing length of response (in same unit as L)\n",
" response_sigma = 0.1\n",
"\n",
" # Define resolution (pixels per dimension)\n",
" N_pixels = 256\n",
"\n",
" # Set up derived constants\n",
" k_0 = 1./correlation_length\n",
" # Note that field_variance**2 = a*k_0/4. for this analytic form of power\n",
" # spectrum\n",
" a = field_variance**2/k_0*4.\n",
" pow_spec = (lambda k: a / (1 + k/k_0) ** 4)\n",
" pixel_width = L/N_pixels\n",
"\n",
" # Set up the geometry\n",
" s_space = ift.RGSpace([N_pixels, N_pixels], distances=pixel_width)\n",
" fft = ift.FFTOperator(s_space)\n",
" h_space = fft.target[0]\n",
" p_space = ift.PowerSpace(h_space)\n",
"\n",
" # Create mock data\n",
"\n",
" Sh = ift.create_power_operator(h_space, power_spectrum=pow_spec)\n",
"\n",
" sp = ift.PS_field(p_space, pow_spec)\n",
" sh = ift.power_synthesize(sp, real_signal=True)\n",
" ss = fft.inverse_times(sh)\n",
"\n",
" R = ift.FFTSmoothingOperator(s_space, sigma=response_sigma)\n",
"\n",
" signal_to_noise = 1\n",
" diag = ift.Field(s_space, ss.var()/signal_to_noise).weight(1)\n",
" N = ift.DiagonalOperator(diag)\n",
" n = ift.Field.from_random(domain=s_space,\n",
" random_type='normal',\n",
" std=ss.std()/np.sqrt(signal_to_noise),\n",
" mean=0)\n",
"\n",
" d = R(ss) + n\n",
"\n",
" # Wiener filter\n",
"\n",
" j = R.adjoint_times(N.inverse_times(d))\n",
" IC = ift.GradientNormController(verbose=True, iteration_limit=500,\n",
" tol_abs_gradnorm=0.1)\n",
" inverter = ift.ConjugateGradient(controller=IC)\n",
" S_inv = fft.adjoint*Sh.inverse*fft\n",
" D = (R.adjoint*N.inverse*R + S_inv).inverse\n",
" # MR FIXME: we can/should provide a preconditioner here as well!\n",
" D = ift.InversionEnabler(D, inverter)\n",
" m = D(j)\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"ift.plot(m)\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"ift.plot(d)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"ift.plot(ss)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 2",
"language": "python",
"name": "python2"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 2
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython2",
"version": "2.7.12"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
rm -rf docs/build docs/source/mod
sphinx-apidoc -l -e -d 3 -o docs/source/mod nifty4
sphinx-apidoc -l -e -d 2 -o docs/source/mod nifty4
sphinx-build -b html docs/source/ docs/build/
NIFTy Code
==========
The NIFTy code is divided in the concepts Domains, Fields, Operators and Minimization
.. toctree::
:maxdepth: 2
:caption: Concepts
:glob:
Domains <concepts/domains>
Fields <concepts/field>
Operators <concepts/operators>
Minimization <concepts/minimization>
NIFTy's domain classes
======================
.. currentmodule:: nifty4
**Abstract base class**
:py:class:`Domain` is the abstract ancestor for all of NIFTy's domains.
.. toctree::
:maxdepth: 1
Domain <../mod/nifty4.domains.domain>
**Unstructured domains**
Domains can be either *structured* (i.e. there is geometrical information
associated with them, like position in space and volume factors),
or *unstructured* (meaning that the data points have no associated manifold).
Unstructured domains can be described by instances of NIFTy's
:py:class:`UnstructuredDomain` class.
.. toctree::
:maxdepth: 1
UnstructuredDomain <../mod/nifty4.domains.unstructured_domain>
**Structured domains**
In contrast to unstructured domains, these domains have an assigned geometry.
NIFTy requires these domains to provide the volume elements of their grid cells.
The additional methods are described in the abstract class
:py:class:`StructuredDomain`.
.. toctree::
:maxdepth: 1
StructuredDomain <../mod/nifty4.domains.structured_domain>
NIFTy comes with several concrete subclasses of :py:class:`StructuredDomain`.
:py:class:`RGSpace` represents a regular Cartesian grid with an arbitrary
number of dimensions, which is supposed to be periodic in each dimension.
This domain can be constructed to represent either position or harmonic space.
:py:class:`HPSpace` and :py:class:`GLSpace` describe pixelisations of the
2-sphere; their counterpart in harmonic space is :py:class:`LMSpace`, which
contains spherical harmonic coefficients.
:py:class:`PowerSpace` is used to describe one-dimensional power spectra.
.. toctree::
:maxdepth: 1
RGSpace <../mod/nifty4.domains.rg_space>
HPSpace <../mod/nifty4.domains.hp_space>
GLSpace <../mod/nifty4.domains.gl_space>
LMSpace <../mod/nifty4.domains.lm_space>
PowerSpace <../mod/nifty4.domains.power_space>
Fields
======
Description of Fields
.. toctree::
:maxdepth: 1
:caption: Types of Fields
Field <../mod/nifty4.field>
Minimization
============
Description of Minimization
.. toctree::
:maxdepth: 1
:caption: Minimization Concepts
Conjugate Gradient <../mod/nifty4.minimization.conjugate_gradient>
Descent Minimizer <../mod/nifty4.minimization.descent_minimizer>
Energy <../mod/nifty4.minimization.energy>
Iteration Controller <../mod/nifty4.minimization.iteration_controller>
Line Energy <../mod/nifty4.minimization.line_energy>
Line Search <../mod/nifty4.minimization.line_search>
Line Search Strong Wolfe <../mod/nifty4.minimization.line_search_strong_wolfe>
Minimizer <../mod/nifty4.minimization.minimizer>
Nonlinear Cg <../mod/nifty4.minimization.nonlinear_cg>
Quadratic Energy <../mod/nifty4.minimization.quadratic_energy>
Relaxed Newton <../mod/nifty4.minimization.relaxed_newton>
Scipy Minimizer <../mod/nifty4.minimization.scipy_minimizer>
Steepest Descent <../mod/nifty4.minimization.steepest_descent>
VL BFGS <../mod/nifty4.minimization.vl_bfgs>
Gradient Norm Controller <../mod/nifty4.minimization.gradient_norm_controller>
Operators
=========
Description of Operators
.. toctree::
:maxdepth: 1
:caption: Commonly used operators
LinearOperator <../mod/nifty4.operators.linear_operator>
EndomorphicOperator <../mod/nifty4.operators.endomorphic_operator>
ScalingOperator <../mod/nifty4.operators.scaling_operator>
DiagonalOperator <../mod/nifty4.operators.diagonal_operator>
HarmonicTransformOperator <../mod/nifty4.operators.harmonic_transform_operator>
PowerProjectionOperator <../mod/nifty4.operators.power_projection_operator>
.. toctree::
:maxdepth: 1
:caption: Not so commonly used operators
FFTOperator <../mod/nifty4.operators.fft_operator>
FFTSmoothingOperator <../mod/nifty4.operators.fft_smoothing_operator>
SmoothnessOperator <../mod/nifty4.operators.smoothness_operator>
InversionEnabler <../mod/nifty4.operators.inversion_enabler>
GeometryRemover <../mod/nifty4.operators.geometry_remover>
.. Adjoint <../mod/nifty4.operators.adjoint_operator>
.. Chain <../mod/nifty4.operators.chain_operator>
.. DOF Projection <../mod/nifty4.operators.dof_projection_operator>
.. Inverse <../mod/nifty4.operators.inverse_operator>
.. Laplace <../mod/nifty4.operators.linear_operator>
.. Sum <../mod/nifty4.operators.sum_operator>
......@@ -116,7 +116,7 @@ exclude_patterns = []
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
#add_module_names = True
add_module_names = False
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
......
......@@ -24,10 +24,12 @@ Contents
........
.. toctree::
:maxdepth: 1
:maxdepth: 2
ift
start
installation
code
Indices and tables
..................
......
Installation
============
In the following, we assume a Debian-based distribution. For other
distributions, the "apt" lines will need slight changes.
NIFTy4 and its mandatory dependencies can be installed via::
sudo apt-get install git libfftw3-dev python python-pip python-dev
pip install --user git+https://gitlab.mpcdf.mpg.de/ift/NIFTy.git@NIFTy_4
(Note: If you encounter problems related to `pyFFTW`, make sure that you are
using a pip-installed `pyFFTW` package. Unfortunately, some distributions are
shipping an incorrectly configured `pyFFTW` package, which does not cooperate
with the installed `FFTW3` libraries.)
Plotting support is added via::
pip install --user matplotlib
Support for spherical harmonic transforms is added via:
pip install --user git+https://gitlab.mpcdf.mpg.de/ift/pyHealpix.git
MPI support is added via::
sudo apt-get install openmpi-bin libopenmpi-dev
pip install --user mpi4py
Scipy-based minimizers are enabled via::
pip install --user scipy
Installation for Python 3
-------------------------
If you want to run NIFTy with Python 3, you need to make the following changes
to the instructions above:
- in all `apt-get` commands, replace `python-*` by `python3-*`
- in all `pip` commands, replace `pip` by `pip3`
......@@ -16,7 +16,7 @@ a continuous signal field is to be recovered.
It is achieved by means of an object-oriented infrastructure that comprises, among others, abstract classes for :ref:`Domains <domains>`, :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>`_.
You should be able to import NIFTy4 like this after a successful `installation <installation.html>`_.
>>> import nifty4 as ift
......@@ -31,7 +31,7 @@ From such a perspective,
- IFT problems largely consist of *minimization* problems involving a large number of equations.
- The equations are built mostly from the application of *linear operators*, but there may also be nonlinear functions involved.
- The unknowns in the equations represent either continuous physical *fields*, or they are simply individual measured *data* points.
- The locations and volume elements attached to discretized *field* values are supplied by *domain* objects. There are many variants of such discretized *domain*s supported by NIFTy4, including Cartesian and spherical geometries and their harmonic counterparts. *Fields* can live on arbitrary products of such *domains*.
- The locations and volume elements attached to discretized *field* values are supplied by *domain* objects. There are many variants of such discretized *domains* supported by NIFTy4, including Cartesian and spherical geometries and their harmonic counterparts. *Fields* can live on arbitrary products of such *domains*.
In the following sections, the concepts briefly presented here will be discussed in more detail; this is done in reversed order of their introduction, to avoid forward references.
......@@ -41,7 +41,7 @@ In the following sections, the concepts briefly presented here will be discussed
Domains
.......
One of the fundamental building blocks of the NIFTy4 framework is the /domain/.
One of the fundamental building blocks of the NIFTy4 framework is the *domain*.
Its required capabilities are expressed by the abstract :py:class:`Domain` class.
A domain must be able to answer the following queries:
......@@ -49,6 +49,7 @@ A domain must be able to answer the following queries:
- the shape of the array that is supposed to hold them
- equality/inequality to another :py:class:`Domain` instance
Unstructured domains
....................
......@@ -76,14 +77,15 @@ Examples for structured domains are
Among these, :py:class:`RGSpace` can be harmonic or not (depending on constructor arguments), :py:class:`GLSpace` is a pure position domain (i.e. nonharmonic), and :py:class:`LMSpace` is always harmonic.
Full domains
............
Combinations of domains
.......................
A field can live on a single domain, but it can also live on a product of domains (or no domain at all, in which case it is a scalar).
The tuple of domain on which a field lives is described by the :py:class:`DomainTuple` class.
A :py:class:`DomainTuple` object can be constructed from
- a single instance of anything derived from :py:class:`DomainTuple`
- a single instance of anything derived from :py:class:`Domain`
- a tuple of such instances (possibly empty)
- another :py:class:`DomainTuple` object
......@@ -125,10 +127,10 @@ There are two domains associated with a :py:class:`LinearOperator`: a *domain* a
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.
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::
As an example, if ``A``, ``B`` and ``C`` are of type :py:class:`LinearOperator` and ``f1`` and ``f2`` are :py:class:`Field` s, writing::
X = A*B.inverse*A.adjoint + C
f2 = X(f1)
......
......@@ -19,6 +19,7 @@
from builtins import object
from ..field import Field
class StatCalculator(object):
def __init__(self):
self._count = 0
......
......@@ -72,7 +72,6 @@ class Energy_Tests(unittest.TestCase):
tol = 1e-5
assert_allclose(a, b, rtol=tol, atol=tol)
@expand(product([ift.RGSpace(64, distances=.789),
ift.RGSpace([32, 32], distances=.789)],
[ift.library.Tanh, ift.library.Exponential,
......
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