Commit ac8f1fe2 authored by Theo Steininger's avatar Theo Steininger

Refactored critical power files.

parent bce18b72
Pipeline #14785 passed with stage
in 6 minutes and 43 seconds
...@@ -123,9 +123,6 @@ if __name__ == "__main__": ...@@ -123,9 +123,6 @@ if __name__ == "__main__":
callback=convergence_measure, callback=convergence_measure,
max_history_length=3) max_history_length=3)
inverter = ConjugateGradient(convergence_level=1,
convergence_tolerance=10e-4,
preconditioner=None)
# Setting starting position # Setting starting position
flat_power = Field(p_space,val=10e-8) flat_power = Field(p_space,val=10e-8)
m0 = flat_power.power_synthesize(real_signal=True) m0 = flat_power.power_synthesize(real_signal=True)
...@@ -144,7 +141,7 @@ if __name__ == "__main__": ...@@ -144,7 +141,7 @@ if __name__ == "__main__":
D0 = map_energy.curvature D0 = map_energy.curvature
m0 = D0.inverse_times(j) m0 = D0.inverse_times(j)
# Initializing the power energy with updated parameters # Initializing the power energy with updated parameters
power_energy = CriticalPowerEnergy(position=t0, m=m0, D=D0, sigma=10., samples=3, inverter=inverter) power_energy = CriticalPowerEnergy(position=t0, m=m0, D=D0, smoothness_prior=10., samples=3)
(power_energy, convergence) = minimizer1(power_energy) (power_energy, convergence) = minimizer1(power_energy)
...@@ -153,6 +150,8 @@ if __name__ == "__main__": ...@@ -153,6 +150,8 @@ if __name__ == "__main__":
t0.val = power_energy.position.val.real t0.val = power_energy.position.val.real
# Plotting current estimate # Plotting current estimate
plot_parameters(m0,t0,log(sp), data_power) print i
if i%50 == 0:
plot_parameters(m0,t0,log(sp), data_power)
import numpy as np
from nifty.energies.energy import Energy from nifty.energies.energy import Energy
from nifty.operators.smoothness_operator import SmoothnessOperator from nifty.operators.smoothness_operator import SmoothnessOperator
from nifty.library.critical_filter import CriticalPowerCurvature from nifty.library.critical_filter import CriticalPowerCurvature
...@@ -10,9 +12,10 @@ from nifty import Field, exp ...@@ -10,9 +12,10 @@ from nifty import Field, exp
class CriticalPowerEnergy(Energy): class CriticalPowerEnergy(Energy):
"""The Energy of the power spectrum according to the critical filter. """The Energy of the power spectrum according to the critical filter.
It describes the energy of the logarithmic amplitudes of the power spectrum of It describes the energy of the logarithmic amplitudes of the power spectrum
a Gaussian random field under reconstruction uncertainty with smoothness and of a Gaussian random field under reconstruction uncertainty with smoothness
inverse gamma prior. It is used to infer the correlation structure of a correlated signal. and inverse gamma prior. It is used to infer the correlation structure of a
correlated signal.
Parameters Parameters
---------- ----------
...@@ -25,20 +28,21 @@ class CriticalPowerEnergy(Energy): ...@@ -25,20 +28,21 @@ class CriticalPowerEnergy(Energy):
If not specified, the map is assumed to be no reconstruction. If not specified, the map is assumed to be no reconstruction.
default : None default : None
alpha : float alpha : float
The spectral prior of the inverse gamma distribution. 1.0 corresponds to The spectral prior of the inverse gamma distribution. 1.0 corresponds
non-informative. to non-informative.
default : 1.0 default : 1.0
q : float q : float
The cutoff parameter of the inverse gamma distribution. 0.0 corresponds to The cutoff parameter of the inverse gamma distribution. 0.0 corresponds
non-informative. to non-informative.
default : 0.0
smoothness_prior : float
Controls the strength of the smoothness prior
default : 0.0 default : 0.0
sigma : float
The parameter of the smoothness prior.
default : ??? None? ???????
logarithmic : boolean logarithmic : boolean
Whether smoothness acts on linear or logarithmic scale. Whether smoothness acts on linear or logarithmic scale.
samples : integer samples : integer
Number of samples used for the estimation of the uncertainty corrections. Number of samples used for the estimation of the uncertainty
corrections.
default : 3 default : 3
w : Field w : Field
The contribution from the map with or without uncertainty. It is used The contribution from the map with or without uncertainty. It is used
...@@ -49,76 +53,72 @@ class CriticalPowerEnergy(Energy): ...@@ -49,76 +53,72 @@ class CriticalPowerEnergy(Energy):
default : None default : None
""" """
def __init__(self, position, m, D=None, alpha =1.0, q=0., sigma=0., def __init__(self, position, m, D=None, alpha=1.0, q=0.,
logarithmic = True, samples=3, w=None, inverter=None): smoothness_prior=0., logarithmic=True, samples=3, w=None):
super(CriticalPowerEnergy, self).__init__(position = position) super(CriticalPowerEnergy, self).__init__(position=position)
self.m = m self.m = m
self.D = D self.D = D
self.samples = samples self.samples = samples
self.sigma = sigma self.smoothness_prior = np.float(smoothness_prior)
self.alpha = Field(self.position.domain, val=alpha) self.alpha = Field(self.position.domain, val=alpha)
self.q = Field(self.position.domain, val=q) self.q = Field(self.position.domain, val=q)
self.T = SmoothnessOperator(domain=self.position.domain[0], sigma=self.sigma, self.T = SmoothnessOperator(domain=self.position.domain[0],
strength=self.smoothness_prior,
logarithmic=logarithmic) logarithmic=logarithmic)
self.rho = self.position.domain[0].rho self.rho = self.position.domain[0].rho
self.inverter = inverter self._w = w if w is not None else None
self.w = w
if self.w is None:
self.w = self._calculate_w(self.m, self.D, self.samples)
self.theta = (exp(-self.position) * (self.q + self.w / 2.))
def at(self, position): def at(self, position):
return self.__class__(position, self.m, D=self.D, return self.__class__(position, self.m, D=self.D, alpha=self.alpha,
alpha =self.alpha, q=self.q, smoothness_prior=self.smoothness_prior,
q=self.q, w=self.w, samples=self.samples)
sigma=self.sigma, w=self.w,
samples=self.samples)
@property @property
def value(self): def value(self):
energy = self._theta.vdot(Field(self.position.domain,val=1.), bare= True) energy = self._theta.sum()
energy += self.position.vdot(self._rho_prime, bare=True) energy += self.position.vdot(self._rho_prime, bare=True)
energy += 0.5 * self.position.vdot(self._Tt) energy += 0.5 * self.position.vdot(self._Tt)
return energy.real return energy.real
@property @property
def gradient(self): def gradient(self):
gradient = - self._theta.weight(-1) gradient = -self._theta.weight(-1)
gradient += (self._rho_prime).weight(-1) gradient += (self._rho_prime).weight(-1)
gradient += self._Tt gradient += self._Tt
gradient.val = gradient.val.real gradient.val = gradient.val.real
return gradient return gradient
@property @property
def curvature(self): def curvature(self):
curvature = CriticalPowerCurvature(theta=self._theta.weight(-1), T=self.T, curvature = CriticalPowerCurvature(theta=self._theta.weight(-1),
inverter=self.inverter) T=self.T)
return curvature return curvature
def _calculate_w(self, m, D, samples): @property
w = Field(domain=self.position.domain, val=0. , dtype=m.dtype) def w(self):
if D is not None: if self._w is None:
for i in range(samples): w = Field(domain=self.position.domain, val=0., dtype=self.m.dtype)
posterior_sample = generate_posterior_sample(m, D, inverter = self.inverter) if self.D is not None:
projected_sample = posterior_sample.power_analyze( for i in range(self.samples):
logarithmic=self.position.domain[0].config["logarithmic"], posterior_sample = generate_posterior_sample(
nbin= self.position.domain[0].config["nbin"]) self.m, self.D)
w += (projected_sample) * self.rho projected_sample = posterior_sample.power_analyze(
w /= float(samples) logarithmic=self.position.domain[0].config["logarithmic"],
else: nbin=self.position.domain[0].config["nbin"])
w = m.power_analyze( w += (projected_sample) * self.rho
logarithmic=self.position.domain[0].config["logarithmic"], w /= float(self.samples)
nbin=self.position.domain[0].config["nbin"]) else:
w *= self.rho w = self.m.power_analyze(
logarithmic=self.position.domain[0].config["logarithmic"],
return w nbin=self.position.domain[0].config["nbin"])
w *= self.rho
self._w = w
return self._w
@property @property
@memo @memo
def _theta(self): def _theta(self):
return (exp(-self.position) * (self.q + self.w / 2.)) return exp(-self.position) * (self.q + self.w / 2.)
@property @property
@memo @memo
...@@ -129,4 +129,3 @@ class CriticalPowerEnergy(Energy): ...@@ -129,4 +129,3 @@ class CriticalPowerEnergy(Energy):
@memo @memo
def _Tt(self): def _Tt(self):
return self.T(self.position) return self.T(self.position)
...@@ -29,7 +29,6 @@ class WienerFilterEnergy(Energy): ...@@ -29,7 +29,6 @@ class WienerFilterEnergy(Energy):
self.R = R self.R = R
self.N = N self.N = N
self.S = S self.S = S
self.inverter = inverter
def at(self, position): def at(self, position):
return self.__class__(position=position, d=self.d, R=self.R, N=self.N, return self.__class__(position=position, d=self.d, R=self.R, N=self.N,
...@@ -48,10 +47,8 @@ class WienerFilterEnergy(Energy): ...@@ -48,10 +47,8 @@ class WienerFilterEnergy(Energy):
@property @property
@memo @memo
def curvature(self): def curvature(self):
return WienerFilterCurvature(R=self.R, N=self.N, S=self.S, return WienerFilterCurvature(R=self.R, N=self.N, S=self.S)
inverter=self.inverter)
@property
@memo @memo
def _Dx(self): def _Dx(self):
return self.curvature(self.position) return self.curvature(self.position)
......
...@@ -38,7 +38,8 @@ class InvertibleOperatorMixin(object): ...@@ -38,7 +38,8 @@ class InvertibleOperatorMixin(object):
(default: ConjugateGradient) (default: ConjugateGradient)
preconditioner : LinearOperator preconditioner : LinearOperator
Preconditions the minimizaion problem Preconditioner that is used by ConjugateGraduent if no minimizer was
given.
Attributes Attributes
---------- ----------
......
...@@ -5,14 +5,17 @@ from nifty.operators.laplace_operator import LaplaceOperator ...@@ -5,14 +5,17 @@ from nifty.operators.laplace_operator import LaplaceOperator
class SmoothnessOperator(EndomorphicOperator): class SmoothnessOperator(EndomorphicOperator):
"""An operator measuring the smoothness on an irregular grid with respect to some scale. """An operator measuring the smoothness on an irregular grid with respect
to some scale.
This operator applies the irregular LaplaceOperator and its adjoint to some Field over a This operator applies the irregular LaplaceOperator and its adjoint to some
PowerSpace which corresponds to its smoothness and weights the result with a scale parameter sigma. Field over a PowerSpace which corresponds to its smoothness and weights the
It is used in the smoothness prior terms of the CriticalPowerEnergy. For this purpose we result with a scale parameter sigma. It is used in the smoothness prior
use free boundary conditions in the LaplaceOperator, having no curvature at both ends. terms of the CriticalPowerEnergy. For this purpose we use free boundary
In addition the first entry is ignored as well, corresponding to the overall mean of the map. conditions in the LaplaceOperator, having no curvature at both ends. In
The mean is therefore not considered in the smoothness prior. addition the first entry is ignored as well, corresponding to the overall
mean of the map. The mean is therefore not considered in the smoothness
prior.
Parameters Parameters
...@@ -26,7 +29,8 @@ class SmoothnessOperator(EndomorphicOperator): ...@@ -26,7 +29,8 @@ class SmoothnessOperator(EndomorphicOperator):
# ---Overwritten properties and methods--- # ---Overwritten properties and methods---
def __init__(self, domain, sigma, logarithmic=True, default_spaces=None): def __init__(self, domain, strength=1., logarithmic=True,
default_spaces=None):
super(SmoothnessOperator, self).__init__(default_spaces=default_spaces) super(SmoothnessOperator, self).__init__(default_spaces=default_spaces)
...@@ -37,10 +41,10 @@ class SmoothnessOperator(EndomorphicOperator): ...@@ -37,10 +41,10 @@ class SmoothnessOperator(EndomorphicOperator):
if not isinstance(self.domain[0], PowerSpace): if not isinstance(self.domain[0], PowerSpace):
raise TypeError("The domain must contain exactly one PowerSpace.") raise TypeError("The domain must contain exactly one PowerSpace.")
if sigma <= 0: if strength <= 0:
raise ValueError("ERROR: invalid sigma.") raise ValueError("ERROR: invalid sigma.")
self._sigma = sigma self._strength = strength
self._laplace = LaplaceOperator(domain=self.domain, self._laplace = LaplaceOperator(domain=self.domain,
logarithmic=logarithmic) logarithmic=logarithmic)
...@@ -68,11 +72,17 @@ class SmoothnessOperator(EndomorphicOperator): ...@@ -68,11 +72,17 @@ class SmoothnessOperator(EndomorphicOperator):
return False return False
def _times(self, x, spaces): def _times(self, x, spaces):
res = self._laplace.adjoint_times(self._laplace(x, spaces), spaces) if self._strength != 0:
return (1./self.sigma)**2*res result = self._laplace.adjoint_times(self._laplace(x, spaces),
spaces)
result *= self._strength**2
else:
result = x.copy_empty()
result.val[:] = 0
return result
# ---Added properties and methods--- # ---Added properties and methods---
@property @property
def sigma(self): def strength(self):
return self._sigma return self._strength
...@@ -64,11 +64,13 @@ def create_power_operator(domain, power_spectrum, dtype=None, ...@@ -64,11 +64,13 @@ def create_power_operator(domain, power_spectrum, dtype=None,
return DiagonalOperator(domain, diagonal=f, bare=True) return DiagonalOperator(domain, diagonal=f, bare=True)
def generate_posterior_sample(mean, covariance, inverter=None): def generate_posterior_sample(mean, covariance):
""" Generates a posterior sample from a Gaussian distribution with given mean and covariance """ Generates a posterior sample from a Gaussian distribution with given
mean and covariance
This method generates samples by setting up the observation and reconstruction of a mock signal This method generates samples by setting up the observation and
in order to obtain residuals of the right correlation which are added to the given mean. reconstruction of a mock signal in order to obtain residuals of the right
correlation which are added to the given mean.
Parameters Parameters
---------- ----------
...@@ -77,9 +79,6 @@ def generate_posterior_sample(mean, covariance, inverter=None): ...@@ -77,9 +79,6 @@ def generate_posterior_sample(mean, covariance, inverter=None):
covariance : WienerFilterCurvature covariance : WienerFilterCurvature
The posterior correlation structure consisting of a The posterior correlation structure consisting of a
response operator, noise covariance and prior signal covariance response operator, noise covariance and prior signal covariance
inverter : ConjugateGradient *optional*
the conjugate gradient used to invert the curvature for the Wiener filter.
default : None
Returns Returns
------- -------
...@@ -91,8 +90,6 @@ def generate_posterior_sample(mean, covariance, inverter=None): ...@@ -91,8 +90,6 @@ def generate_posterior_sample(mean, covariance, inverter=None):
S = covariance.S S = covariance.S
R = covariance.R R = covariance.R
N = covariance.N N = covariance.N
if inverter is None:
inverter = ConjugateGradient(preconditioner=S)
power = S.diagonal().power_analyze()**.5 power = S.diagonal().power_analyze()**.5
mock_signal = power.power_synthesize(real_signal=True) mock_signal = power.power_synthesize(real_signal=True)
......
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