ChangeLog 7.13 KB
Newer Older
Martin Reinecke's avatar
Martin Reinecke committed
1
2
Changes since NIFTy 5:

Martin Reinecke's avatar
Martin Reinecke committed
3
4
5
6
Minimum Python version increased to 3.6
=======================================


7
8
9
10
11
12
13
14
15
16
17
18
19
New operators
=============

In addition to the below changes, the following operators were introduced:

* UniformOperator: Transforms a Gaussian into a uniform distribution
* VariableCovarianceGaussianEnergy: Energy operator for inferring covariances
* MultiLinearEinsum: Multi-linear version of numpy's einsum with derivates
* LinearEinsum: Linear version of numpy's einsum with one free field
* PartialConjugate: Conjugates parts of a multi-field
* SliceOperator: Geometry preserving mask operator
* SplitOperator: Splits a single field into a multi-field

Martin Reinecke's avatar
Martin Reinecke committed
20
21
22
23
24
25
26
FFT convention adjusted
=======================

When going to harmonic space, NIFTy's FFT operator now uses a minus sign in the
exponent (and, consequently, a plus sign on the adjoint transform). This
convention is consistent with almost all other numerical FFT libraries.

Martin Reinecke's avatar
Martin Reinecke committed
27
28
29
Interface change in EndomorphicOperator.draw_sample()
=====================================================

Philipp Arras's avatar
Philipp Arras committed
30
Both complex-valued and real-valued Gaussian probability distributions have
Martin Reinecke's avatar
Martin Reinecke committed
31
Hermitian and positive endomorphisms as covariance. Just by looking at an
Philipp Arras's avatar
Philipp Arras committed
32
33
34
35
36
37
endomorphic operator itself it is not clear whether it is viewed as covariance
for real or complex Gaussians when a sample of the respective distribution shall
be drawn. Therefore, we introduce the method `draw_sample_with_dtype()` which
needs to be given the data type of the probability distribution. This function
is implemented for all operators which actually draw random numbers
(`DiagonalOperator` and `ScalingOperator`). The class `SamplingDtypeSetter` acts
Martin Reinecke's avatar
Martin Reinecke committed
38
as a wrapper for this kind of operators in order to fix the data type of the
Philipp Arras's avatar
Philipp Arras committed
39
40
41
42
43
44
45
46
47
48
49
distribution. Samples from these operators can be drawn with `.draw_sample()`.
In order to dive into those subtleties I suggest running the following code and
playing around with the dtypes.

```
import nifty6 as ift
import numpy as np

dom = ift.UnstructuredDomain(5)
dtype = [np.float64, np.complex128][1]
invcov = ift.ScalingOperator(dom, 3)
Martin Reinecke's avatar
Martin Reinecke committed
50
e = ift.GaussianEnergy(mean=ift.from_random(dom, 'normal', dtype=dtype),
Philipp Arras's avatar
Philipp Arras committed
51
                       inverse_covariance=invcov)
Martin Reinecke's avatar
Martin Reinecke committed
52
pos = ift.from_random(dom, 'normal', dtype=np.complex128)
Philipp Arras's avatar
Philipp Arras committed
53
54
55
56
57
lin = e(ift.Linearization.make_var(pos, want_metric=True))
met = lin.metric
print(met)
print(met.draw_sample())
```
Martin Reinecke's avatar
Martin Reinecke committed
58

Philipp Arras's avatar
Philipp Arras committed
59
60
61
62
63
64
MPI parallelisation over samples in MetricGaussianKL
====================================================

The classes `MetricGaussianKL` and `MetricGaussianKL_MPI` have been unified
into one `MetricGaussianKL` class which has MPI support built in.

Martin Reinecke's avatar
Martin Reinecke committed
65
66
67
68
69
70
71
72
73
New approach for random number generation
=========================================

The code now uses `numpy`'s new `SeedSequence` and `Generator` classes for the
production of random numbers (introduced in numpy 1.17. This greatly simplifies
the generation of reproducible random numbers in the presence of MPI parallelism
and leads to cleaner code overall. Please see the documentation of
`nifty6.random` for details.

Rouven Lemmerz's avatar
Rouven Lemmerz committed
74
75
76
77
78
79
80
Interface Change for from_random and OuterProduct
=================================================

The sugar.from_random, Field.from_random, MultiField.from_random now take domain
as the first argument and default to 'normal' for the second argument.
Likewise OuterProduct takes domain as the first argument and a field as the second.

Philipp Arras's avatar
Philipp Arras committed
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
Interface Change for non-linear Operators
=========================================

The method `Operator.apply()` takes a `Linearization` or a `Field` or a
`MultiField` as input. This has not changed. However, now each non-linear
operator assumes that the input `Linearization` comes with an identity operator
as jacobian. Also it is assumed that the `apply()` method returns a
`Linearization` with the jacobian of the operator itself. The user is not in
charge anymore of stacking together the jacobians of operator chains. Something
like `x.jac` should not appear in any self-written `apply()` methods. The method
`Operator._check_input` tests if this condition is met. The same goes for the
metric. There is no need anymore to call `SandwichOperator` in an `apply()`
method when implementing new energies. This change should not lead to unexpected
behaviour since both `Operator._check_input()` and
`extra.check_jacobian_consistency()` tests for the new conditions to be
fulfilled.

Martin Reinecke's avatar
Martin Reinecke committed
98
99
100
101
102
103
104
105
106
107
108
109
Special functions for complete Field reduction operations
=========================================================

So far, reduction operations called on Fields (like `vdot`, `sum`, `integrate`,
`mean`, `var`, `std`, `prod` etc.) returned a scalar when the reduction was
carried out over all domains, and otherwise a `Field`.
Having the data type of the returned value depend on input parameters is
extremely confusing, so all of these reduction operations now always return a
Field. We also introduced another set of reduction operations which always
operate over all subdomains and therefore don't take a `spaces` argument; they
are named `s_vdot`, `s_sum` etc. and always return a scalar.

110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
Updates regarding correlated fields
===================================

The most commonly used model for homogeneous and isotropic correlated fields in
nifty5 has been `SLAmplitude` combined with `CorrelatedField`. This model
exhibits unintuitive couplings between its parameters and as been replaced
by `CorrelatedFieldMaker` in NIFTy 6. This model aims to conceptionally provide
the same functionality. However, internally it works quite differently. Therefore,
specific classes for `SLAmplitude` like `LogRGSpace`, `QHTOperator`, `ExpTransform`,
`SlopeOperator`, `SymmetrizingOperator`, `CepstrumOperator`, `CorrelatedField`
and `MfCorrelatedField` are not needed anymore and have been removed. In general,
`CorrelatedFieldMaker` feels to be better conditioned leading to faster convergence
but it is hard to make explicit tests since the two approaches cannot be mapped
onto each other exactly. We experienced that preconditioning in the `MetricGaussianKL`
via `napprox` breaks the inference scheme with the new model so `napprox` may not
be used here.
Martin Reinecke's avatar
merge    
Martin Reinecke committed
126

Lukas Platz's avatar
Lukas Platz committed
127
128
Removal of the standard MPI parallelization scheme:
===================================================
Martin Reinecke's avatar
Martin Reinecke committed
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145

When several MPI tasks are present, NIFTy5 distributes every Field over these
tasks by splitting it along the first axis. This approach to parallelism is not
very efficient, and it has not been used by anyone for several years, so we
decided to remove it, which led to many simplifications within NIFTy.
User-visible changes:
- the methods `to_global_data`, `from_global_data`, `from_local_data` and
  the property `local_data` have been removed from `Field` and `MultiField`.
  Instead there are now the property `val` (returning a read-only numpy.ndarray
  for `Field` and a dictionary of read-only numpy.ndarrays for `MultiField`) and
  the method `val_rw()` (returning the same structures with writable copies of
  the arrays). Fields and MultiFields can be created from such structures using
  the static method `from_raw`
- the functions `from_global_data` and `from_local_data` in `sugar` have been
  replaced by a single function called `makeField`
- the property `local_shape` has been removed from `Domain` (and subclasses)
  and `DomainTuple`.