Commit 14926005 authored by Philipp Arras's avatar Philipp Arras

Add prior statistics output summary

parent ab3fc143
...@@ -84,11 +84,6 @@ if __name__ == '__main__': ...@@ -84,11 +84,6 @@ if __name__ == '__main__':
-1.5, .5, -1.5, .5,
'amp2') 'amp2')
correlated_field = cfmaker.finalize(1e-3, 1e-6, '') correlated_field = cfmaker.finalize(1e-3, 1e-6, '')
sams = [ift.from_random('normal',correlated_field.domain)
for _ in range(20)]
print("Prior expected total fluctuations: "+str(
cfmaker.stats(cfmaker.total_fluctuation,sams)[0]))
A1 = cfmaker.amplitudes[0] A1 = cfmaker.amplitudes[0]
A2 = cfmaker.amplitudes[1] A2 = cfmaker.amplitudes[1]
......
...@@ -73,6 +73,20 @@ def _log_vol(power_space): ...@@ -73,6 +73,20 @@ def _log_vol(power_space):
return logk_lengths[1:] - logk_lengths[:-1] return logk_lengths[1:] - logk_lengths[:-1]
def _total_fluctuation_realized(samples):
res = 0.
for s in samples:
res = res + (s - s.mean())**2
return np.sqrt((res/len(samples)).mean())
def _stats(op, samples):
sc = StatCalculator()
for s in samples:
sc.add(op(s.extract(op.domain)))
return sc.mean.to_global_data(), sc.var.sqrt().to_global_data()
class _LognormalMomentMatching(Operator): class _LognormalMomentMatching(Operator):
def __init__(self, mean, sig, key): def __init__(self, mean, sig, key):
key = str(key) key = str(key)
...@@ -329,7 +343,8 @@ class CorrelatedFieldMaker: ...@@ -329,7 +343,8 @@ class CorrelatedFieldMaker:
offset_amplitude_mean, offset_amplitude_mean,
offset_amplitude_stddev, offset_amplitude_stddev,
prefix='', prefix='',
offset=None): offset=None,
prior_info=100):
""" """
offset vs zeromode: volume factor offset vs zeromode: volume factor
""" """
...@@ -343,7 +358,41 @@ class CorrelatedFieldMaker: ...@@ -343,7 +358,41 @@ class CorrelatedFieldMaker:
azm = _LognormalMomentMatching(offset_amplitude_mean, azm = _LognormalMomentMatching(offset_amplitude_mean,
offset_amplitude_stddev, offset_amplitude_stddev,
prefix + 'zeromode') prefix + 'zeromode')
return self.finalize_from_op(azm, prefix) op = self.finalize_from_op(azm, prefix)
if prior_info > 0:
from ..sugar import from_random
samps = [
from_random('normal', op.domain) for _ in range(prior_info)
]
self.statistics_summary(samps)
return op
def statistics_summary(self, samples):
lst = [('Offset amplitude', self.amplitude_total_offset),
('Total fluctuation amplitude', self.total_fluctuation)]
namps = len(self.amplitudes)
if namps > 1:
for ii in range(namps):
lst.append(('Slice fluctuation (space {})'.format(ii),
self.slice_fluctuation(ii)))
lst.append(('Average fluctuation (space {})'.format(ii),
self.average_fluctuation(ii)))
for kk, op in lst:
mean, stddev = _stats(op, samples)
print('{}: {:.02E} ± {:.02E}'.format(kk, mean, stddev))
def moment_slice_to_average(self, fluctuations_slice_mean, nsamples=1000):
fluctuations_slice_mean = float(fluctuations_slice_mean)
assert fluctuations_slice_mean > 0
scm = 1.
for a in self._a:
m, std = a.fluctuation_amplitude.mean, a.fluctuation_amplitude.std
mu, sig = _lognormal_moments(m, std)
flm = np.exp(mu + sig*np.random.normal(size=nsamples))
scm *= flm**2 + 1.
return fluctuations_slice_mean/np.mean(np.sqrt(scm))
@property @property
def amplitudes(self): def amplitudes(self):
...@@ -355,6 +404,7 @@ class CorrelatedFieldMaker: ...@@ -355,6 +404,7 @@ class CorrelatedFieldMaker:
@property @property
def total_fluctuation(self): def total_fluctuation(self):
"""Returns operator which acts on prior or posterior samples"""
if len(self._a) == 0: if len(self._a) == 0:
raise NotImplementedError raise NotImplementedError
if len(self._a) == 1: if len(self._a) == 1:
...@@ -366,6 +416,7 @@ class CorrelatedFieldMaker: ...@@ -366,6 +416,7 @@ class CorrelatedFieldMaker:
return (Adder(full(q.target, -1.)) @ q).sqrt() return (Adder(full(q.target, -1.)) @ q).sqrt()
def slice_fluctuation(self, space): def slice_fluctuation(self, space):
"""Returns operator which acts on prior or posterior samples"""
if len(self._a) == 0: if len(self._a) == 0:
raise NotImplementedError raise NotImplementedError
assert space < len(self._a) assert space < len(self._a)
...@@ -381,6 +432,7 @@ class CorrelatedFieldMaker: ...@@ -381,6 +432,7 @@ class CorrelatedFieldMaker:
return q.sqrt() return q.sqrt()
def average_fluctuation(self, space): def average_fluctuation(self, space):
"""Returns operator which acts on prior or posterior samples"""
if len(self._a) == 0: if len(self._a) == 0:
raise NotImplementedError raise NotImplementedError
assert space < len(self._a) assert space < len(self._a)
...@@ -388,61 +440,46 @@ class CorrelatedFieldMaker: ...@@ -388,61 +440,46 @@ class CorrelatedFieldMaker:
return self._a[0].fluctuation_amplitude return self._a[0].fluctuation_amplitude
return self._a[space].fluctuation_amplitude return self._a[space].fluctuation_amplitude
def average_fluctuation_realized(self, samples, space): @staticmethod
ldom = len(samples[0].domain) def offset_amplitude_realized(samples):
assert space < ldom
if ldom == 1:
return self.total_fluctuation_realized(samples)
spaces = ()
for i in range(ldom):
if i != space:
spaces += (i,)
res = 0. res = 0.
for s in samples: for s in samples:
r = s.mean(spaces) res += s.mean()**2
res = res + (r - r.mean())**2 return np.sqrt(res/len(samples))
res = res/len(samples)
return np.sqrt(res.mean())
def slice_fluctuation_realized(self, samples, space): @staticmethod
def total_fluctuation_realized(samples):
return _total_fluctuation_realized(samples)
@staticmethod
def slice_fluctuation_realized(samples, space):
"""Computes slice fluctuations from collection of field (defined in signal
space) realizations."""
ldom = len(samples[0].domain) ldom = len(samples[0].domain)
assert space < ldom assert space < ldom
if ldom == 1: if ldom == 1:
return self.total_fluctuation_realized(samples) return _total_fluctuation_realized(samples)
res1, res2 = 0., 0. res1, res2 = 0., 0.
for s in samples: for s in samples:
res1 += s**2 res1 += s**2
res2 += s.mean(space)**2 res2 += s.mean(space)**2
return np.sqrt((res1 - res2).mean()/len(samples)) return np.sqrt((res1 - res2).mean()/len(samples))
def moment_slice_to_average(self, fluctuations_slice_mean, nsamples=1000):
fluctuations_slice_mean = float(fluctuations_slice_mean)
assert fluctuations_slice_mean > 0
scm = 1.
for a in self._a:
m, std = a.fluctuation_amplitude.mean, a.fluctuation_amplitude.std
mu, sig = _lognormal_moments(m, std)
flm = np.exp(mu + sig*np.random.normal(size=nsamples))
scm *= flm**2 + 1.
return fluctuations_slice_mean/np.mean(np.sqrt(scm))
@staticmethod @staticmethod
def offset_amplitude_realized(samples): def average_fluctuation_realized(samples, space):
res = 0. """Computes average fluctuations from collection of field (defined in signal
for s in samples: space) realizations."""
res += s.mean()**2 ldom = len(samples[0].domain)
return np.sqrt(res/len(samples)) assert space < ldom
if ldom == 1:
@staticmethod return _total_fluctuation_realized(samples)
def total_fluctuation_realized(samples): spaces = ()
for i in range(ldom):
if i != space:
spaces += (i,)
res = 0. res = 0.
for s in samples: for s in samples:
res = res + (s - s.mean())**2 r = s.mean(spaces)
return np.sqrt((res/len(samples)).mean()) res = res + (r - r.mean())**2
res = res/len(samples)
@staticmethod return np.sqrt(res.mean())
def stats(op, samples):
sc = StatCalculator()
for s in samples:
sc.add(op(s.extract(op.domain)))
return sc.mean.to_global_data(), sc.var.sqrt().to_global_data()
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