Commit 74c2ad71 authored by Gordian Edenhofer's avatar Gordian Edenhofer
Browse files

Simplify arguments to the correlated field model

parent ab97920a
......@@ -120,11 +120,11 @@
%% Cell type:markdown id: tags:
## Before the Action: The Moment-Matched Log-Normal Distribution
Many properties of the correlated field are modelled as being lognormally distributed.
The distribution models are parametrized via their means `_mean` and standard-deviations `_stddev`.
The distribution models are parametrized via their means and standard-deviations (first and second position in tuple).
To get a feeling of how the ratio of the `mean` and `stddev` parameters influences the distribution shape,
here are a few example histograms: (observe the x-axis!)
%% Cell type:code id: tags:
......@@ -164,25 +164,20 @@
``` python
# Neutral model parameters yielding a quasi-constant field
cf_make_pars = {
'offset_mean': 0.,
'offset_std_mean': 1e-3,
'offset_std_std': 1e-16,
'offset_std': (1e-3, 1e-16),
'prefix': ''
}
cf_x_fluct_pars = {
'target_subdomain': x_space,
'fluctuations_mean': 1e-3,
'fluctuations_stddev': 1e-16,
'flexibility_mean': 1e-3,
'flexibility_stddev': 1e-16,
'asperity_mean': 1e-3,
'asperity_stddev': 1e-16,
'loglogavgslope_mean': 0.,
'loglogavgslope_stddev': 1e-16
'fluctuations': (1e-3, 1e-16),
'flexibility': (1e-3, 1e-16),
'asperity': (1e-3, 1e-16),
'loglogavgslope': (0., 1e-16)
}
init_model(cf_make_pars, cf_x_fluct_pars)
```
......@@ -195,125 +190,125 @@
%% Cell type:markdown id: tags:
# Parameter Showcases
## The `fluctuations_` parameters of `add_fluctuations()`
## The `fluctuations` parameters of `add_fluctuations()`
determine the **amplitude of variations along the field dimension**
for which `add_fluctuations` is called.
`fluctuations_mean` set the _average_ amplitude of the fields fluctuations along the given dimension,\
`fluctuations_stddev` sets the width and shape of the amplitude distribution.
`fluctuations[0]` set the _average_ amplitude of the fields fluctuations along the given dimension,\
`fluctuations[1]` sets the width and shape of the amplitude distribution.
The amplitude is modelled as being log-normally distributed,
see `The Moment-Matched Log-Normal Distribution` above for details.
#### `fluctuations_mean`:
#### `fluctuations` mean:
%% Cell type:code id: tags:
``` python
vary_parameter('fluctuations_mean', [0.05, 0.5, 2.], samples_vary_in='xi')
vary_parameter('fluctuations', [(0.05, 1e-16), (0.5, 1e-16), (2., 1e-16)], samples_vary_in='xi')
```
%% Cell type:markdown id: tags:
#### `fluctuations_stddev`:
#### `fluctuations` std:
%% Cell type:code id: tags:
``` python
cf_x_fluct_pars['fluctuations_mean'] = 1.0
vary_parameter('fluctuations_stddev', [0.01, 0.1, 1.0], samples_vary_in='fluctuations')
vary_parameter('fluctuations', [(1., 0.01), (1., 0.1), (1., 1.)], samples_vary_in='fluctuations')
cf_x_fluct_pars['fluctuations'] = (1., 1e-16)
```
%% Cell type:markdown id: tags:
## The `loglogavgslope_` parameters of `add_fluctuations()`
## The `loglogavgslope` parameters of `add_fluctuations()`
determine **the slope of the loglog-linear (power law) component of the power spectrum**.
The slope is modelled to be normally distributed.
#### `loglogavgslope_mean`:
#### `loglogavgslope` mean:
%% Cell type:code id: tags:
``` python
vary_parameter('loglogavgslope_mean', [-3., -1., 1.], samples_vary_in='xi')
vary_parameter('loglogavgslope', [(-3., 1e-16), (-1., 1e-16), (1., 1e-16)], samples_vary_in='xi')
```
%% Cell type:markdown id: tags:
#### `loglogavgslope_stddev`:
#### `loglogavgslope` std:
%% Cell type:code id: tags:
``` python
cf_x_fluct_pars['loglogavgslope_mean'] = -1.0
vary_parameter('loglogavgslope_stddev', [0.01, 0.1, 1.0], samples_vary_in='loglogavgslope')
vary_parameter('loglogavgslope', [(-1., 0.01), (-1., 0.1), (-1., 1.0)], samples_vary_in='loglogavgslope')
cf_x_fluct_pars['loglogavgslope'] = (-1., 1e-16)
```
%% Cell type:markdown id: tags:
## The `flexibility_` parameters of `add_fluctuations()`
## The `flexibility` parameters of `add_fluctuations()`
determine **the amplitude of the integrated Wiener process component of the power spectrum**
(how strong the power spectrum varies besides the power-law).
`flexibility_mean` sets the _average_ amplitude of the i.g.p. component,
`flexibility_stddev` sets how much the amplitude can vary.\
`flexibility[0]` sets the _average_ amplitude of the i.g.p. component,\
`flexibility[1]` sets how much the amplitude can vary.\
These two parameters feed into a moment-matched log-normal distribution model,
see above for a demo of its behavior.
#### `flexibility_mean`:
#### `flexibility` mean:
%% Cell type:code id: tags:
``` python
vary_parameter('flexibility_mean', [0.1, 1.0, 3.0], samples_vary_in='spectrum')
vary_parameter('flexibility', [(0.1, 1e-16), (1.0, 1e-16), (3.0, 1e-16)], samples_vary_in='spectrum')
```
%% Cell type:markdown id: tags:
#### `flexibility_stddev`:
#### `flexibility` std:
%% Cell type:code id: tags:
``` python
cf_x_fluct_pars['flexibility_mean'] = 2.0
vary_parameter('flexibility_stddev', [0.01, 0.1, 1.0], samples_vary_in='flexibility')
vary_parameter('flexibility', [(2., 0.01), (2., 0.1), (2., 1.)], samples_vary_in='flexibility')
cf_x_fluct_pars['flexibility'] = (2., 1e-16)
```
%% Cell type:markdown id: tags:
## The `asperity_` parameters of `add_fluctuations()`
## The `asperity` parameters of `add_fluctuations()`
`asperity_` determines **how rough the integrated Wiener process component of the power spectrum is**.
`asperity` determines **how rough the integrated Wiener process component of the power spectrum is**.
`asperity_mean` sets the average roughness, `asperity_stddev` sets how much the roughness can vary.\
`asperity[0]` sets the average roughness, `asperity[1]` sets how much the roughness can vary.\
These two parameters feed into a moment-matched log-normal distribution model,
see above for a demo of its behavior.
#### `asperity_mean`:
#### `asperity` mean:
%% Cell type:code id: tags:
``` python
vary_parameter('asperity_mean', [0.001, 1.0, 5.0], samples_vary_in='spectrum')
vary_parameter('asperity', [(0.001, 1e-16), (1.0, 1e-16), (5., 1e-16)], samples_vary_in='spectrum')
```
%% Cell type:markdown id: tags:
#### `asperity_stddev`:
#### `asperity` std:
%% Cell type:code id: tags:
``` python
cf_x_fluct_pars['asperity_mean'] = 1.0
vary_parameter('asperity_stddev', [0.01, 0.1, 1.0], samples_vary_in='asperity')
vary_parameter('asperity', [(1., 0.01), (1., 0.1), (1., 1.)], samples_vary_in='asperity')
cf_x_fluct_pars['asperity'] = (1., 1e-16)
```
%% Cell type:markdown id: tags:
## The `offset_mean` parameter of `CorrelatedFieldMaker.make()`
......@@ -324,45 +319,44 @@
%% Cell type:code id: tags:
``` python
# Reset model to neutral
cf_x_fluct_pars['fluctuations_mean'] = 1e-3
cf_x_fluct_pars['flexibility_mean'] = 1e-3
cf_x_fluct_pars['asperity_mean'] = 1e-3
cf_x_fluct_pars['loglogavgslope_mean'] = 1e-3
cf_x_fluct_pars['fluctuations'] = (1e-3, 1e-16)
cf_x_fluct_pars['flexibility'] = (1e-3, 1e-16)
cf_x_fluct_pars['asperity'] = (1e-3, 1e-16)
cf_x_fluct_pars['loglogavgslope'] = (1e-3, 1e-16)
```
%% Cell type:code id: tags:
``` python
vary_parameter('offset_mean', [3., 0., -2.])
```
%% Cell type:markdown id: tags:
## The `offset_std_` parameters of `CorrelatedFieldMaker.make()`
## The `offset_std` parameters of `CorrelatedFieldMaker.make()`
Variation of the global offset of the field are modelled as being log-normally distributed.
See `The Moment-Matched Log-Normal Distribution` above for details.
The `offset_std_mean` parameter sets how much NIFTy will vary the offset *on average*.\
The `offset_std_std` parameters defines the with and shape of the offset variation distribution.
The `offset_std[0]` parameter sets how much NIFTy will vary the offset *on average*.\
The `offset_std[1]` parameters defines the with and shape of the offset variation distribution.
#### `offset_std_mean`:
#### `offset_std` mean:
%% Cell type:code id: tags:
``` python
vary_parameter('offset_std_mean', [1e-16, 0.5, 2.], samples_vary_in='xi')
vary_parameter('offset_std', [(1e-16, 1e-16), (0.5, 1e-16), (2., 1e-16)], samples_vary_in='xi')
```
%% Cell type:markdown id: tags:
#### `offset_std_std`:
#### `offset_std` std:
%% Cell type:code id: tags:
``` python
cf_make_pars['offset_std_mean'] = 1.0
vary_parameter('offset_std_std', [0.01, 0.1, 1.0], samples_vary_in='zeromode')
vary_parameter('offset_std', [(1., 0.01), (1., 0.1), (1., 1.)], samples_vary_in='zeromode')
```
......
......@@ -73,10 +73,10 @@ def main():
sp2 = ift.RGSpace(npix2)
# Set up signal model
cfmaker = ift.CorrelatedFieldMaker.make(0., 1e-2, 1e-6, '')
cfmaker.add_fluctuations(sp1, 0.1, 1e-2, 1, .1, .01, .5, -2, 1., 'amp1')
cfmaker.add_fluctuations(sp2, 0.1, 1e-2, 1, .1, .01, .5,
-1.5, .5, 'amp2')
cfmaker = ift.CorrelatedFieldMaker.make(0., (1e-2, 1e-6), '')
cfmaker.add_fluctuations(sp1, (0.1, 1e-2), (1, .1), (.01, .5), (-2, 1.), 'amp1')
cfmaker.add_fluctuations(sp2, (0.1, 1e-2), (1, .1), (.01, .5),
(-1.5, .5), 'amp2')
correlated_field = cfmaker.finalize()
A1 = cfmaker.normalized_amplitudes[0]
......
......@@ -358,18 +358,16 @@ class CorrelatedFieldMaker:
self._total_N = total_N
@staticmethod
def make(offset_mean, offset_std_mean, offset_std_std, prefix, total_N=0,
dofdex=None):
def make(offset_mean, offset_std, prefix, total_N=0, dofdex=None):
"""Returns a CorrelatedFieldMaker object.
Parameters
----------
offset_mean : float
Mean offset from zero of the correlated field to be made.
offset_std_mean : float
Mean standard deviation of the offset.
offset_std_std : float
Standard deviation of the stddev of the offset.
offset_std : tuple of float
Mean standard deviation and standard deviation of the standard
deviation of the offset. No, this is not a word duplication.
prefix : string
Prefix to the names of the domains of the cf operator to be made.
This determines the names of the operator domain.
......@@ -392,22 +390,19 @@ class CorrelatedFieldMaker:
elif len(dofdex) != total_N:
raise ValueError("length of dofdex needs to match total_N")
N = max(dofdex) + 1 if total_N > 0 else 0
zm = LognormalTransform(offset_std_mean, offset_std_std,
prefix + 'zeromode', N)
if len(offset_std) != 2:
raise TypeError
zm = LognormalTransform(*offset_std, prefix + 'zeromode', N)
if total_N > 0:
zm = _Distributor(dofdex, zm.target, UnstructuredDomain(total_N)) @ zm
return CorrelatedFieldMaker(offset_mean, zm, prefix, total_N)
def add_fluctuations(self,
target_subdomain,
fluctuations_mean,
fluctuations_stddev,
flexibility_mean,
flexibility_stddev,
asperity_mean,
asperity_stddev,
loglogavgslope_mean,
loglogavgslope_stddev,
fluctuations,
flexibility,
asperity,
loglogavgslope,
prefix='',
index=None,
dofdex=None,
......@@ -435,14 +430,14 @@ class CorrelatedFieldMaker:
:class:`~nifty7.domain_tuple.DomainTuple`
Target subdomain on which the correlation structure defined
in this call should hold.
fluctuations_{mean,stddev} : float
fluctuations : tuple of float
Total spectral energy -> Amplitude of the fluctuations
flexibility_{mean,stddev} : float
flexibility : tuple of float or None
Amplitude of the non-power-law power spectrum component
asperity_{mean,stddev} : float
asperity : tuple of float or None
Roughness of the non-power-law power spectrum component
Used to accommodate single frequency peaks
loglogavgslope_{mean,stddev} : float
loglogavgslope : tuple of float
Power law component exponent
prefix : string
prefix of the power spectrum parameter domain names
......@@ -478,37 +473,37 @@ class CorrelatedFieldMaker:
else:
N = 0
target_subdomain = makeDomain(target_subdomain)
prefix = str(prefix)
# assert isinstance(target_subdomain[space], (RGSpace, HPSpace, GLSpace)
# assert isinstance(target_subdomain[space], (RGSpace, HPSpace, GLSpace))
for arg in [fluctuations, loglogavgslope]:
if len(arg) != 2:
raise TypeError
for kw, arg in [("flexibility", flexibility), ("asperity", asperity)]:
if arg is None:
continue
if len(arg) != 2:
raise TypeError
if len(arg) == 2 and (arg[0] <= 0. or arg[1] <= 0.):
ve = "{0} must be strictly positive (or None)"
raise ValueError(ve.format(kw))
if flexibility is None and asperity is not None:
raise ValueError("flexibility may not be disabled on its own")
ve = "{0}_mean and {0}_stddev must be strictly positive (or both zero to disable {0})"
if fluctuations_mean > 0. and fluctuations_stddev > 0.:
fluct = LognormalTransform(fluctuations_mean, fluctuations_stddev,
self._prefix + prefix + 'fluctuations', N)
pre = self._prefix + str(prefix)
fluct = LognormalTransform(*fluctuations, pre + 'fluctuations', N)
if flexibility is not None:
flex = LognormalTransform(*flexibility, pre + 'flexibility', N)
else:
raise ValueError(ve.format("fluctuations"))
if flexibility_mean == 0. and flexibility_stddev == 0.:
if asperity_mean != 0. or asperity_stddev != 0.:
raise ValueError("flexibility may not be disabled on its own")
flex = None
elif flexibility_mean > 0. and flexibility_stddev > 0.:
flex = LognormalTransform(flexibility_mean, flexibility_stddev,
self._prefix + prefix + 'flexibility', N)
if asperity is not None:
asp = LognormalTransform(*asperity, pre + 'asperity', N)
else:
raise ValueError(ve.format("flexibility"))
if asperity_mean == 0. and asperity_stddev == 0.:
asp = None
elif asperity_mean > 0. and asperity_stddev > 0.:
asp = LognormalTransform(asperity_mean, asperity_stddev,
self._prefix + prefix + 'asperity', N)
else:
raise ValueError(ve.format("asperity"))
avgsl = NormalTransform(loglogavgslope_mean, loglogavgslope_stddev,
self._prefix + prefix + 'loglogavgslope', N)
avgsl = NormalTransform(*loglogavgslope, pre + 'loglogavgslope', N)
amp = _Amplitude(PowerSpace(harmonic_partner), fluct, flex, asp, avgsl,
self._azm, target_subdomain[-1].total_volume,
self._prefix + prefix + 'spectrum', dofdex)
pre + 'spectrum', dofdex)
if index is not None:
self._a.insert(index, amp)
......
......@@ -71,11 +71,11 @@ def testAmplitudesInvariants(sspace, N):
astds = 0.2, 1.2
offset_std_mean = 1.3
fa = ift.CorrelatedFieldMaker.make(1.2, offset_std_mean, 1e-2, '', N,
fa = ift.CorrelatedFieldMaker.make(1.2, (offset_std_mean, 1e-2), '', N,
dofdex1)
fa.add_fluctuations(sspace, astds[0], 1e-2, 1.1, 2., 2.1, .5, -2, 1.,
fa.add_fluctuations(sspace, (astds[0], 1e-2), (1.1, 2.), (2.1, .5), (-2, 1.),
'spatial', dofdex=dofdex2)
fa.add_fluctuations(fsspace, astds[1], 1e-2, 3.1, 1., .5, .1, -4, 1.,
fa.add_fluctuations(fsspace, (astds[1], 1e-2), (3.1, 1.), (.5, .1), (-4, 1.),
'freq', dofdex=dofdex3)
op = fa.finalize()
......@@ -103,12 +103,12 @@ def testAmplitudesInvariants(sspace, N):
assert_allclose(slice_fluct_std0, sl_fluct_space, rtol=0.5)
assert_allclose(slice_fluct_std1, sl_fluct_freq, rtol=0.5)
fa = ift.CorrelatedFieldMaker.make(0., offset_std_mean, .1, '', N, dofdex1)
fa.add_fluctuations(fsspace, astds[1], 1., 3.1, 1., .5, .1, -4, 1., 'freq',
fa = ift.CorrelatedFieldMaker.make(0., (offset_std_mean, .1), '', N, dofdex1)
fa.add_fluctuations(fsspace, (astds[1], 1.), (3.1, 1.), (.5, .1), (-4, 1.), 'freq',
dofdex=dofdex3)
m = 3.
x = fa.moment_slice_to_average(m)
fa.add_fluctuations(sspace, x, 1.5, 1.1, 2., 2.1, .5, -2, 1., 'spatial', 0,
fa.add_fluctuations(sspace, (x, 1.5), (1.1, 2.), (2.1, .5), (-2, 1.), 'spatial', 0,
dofdex=dofdex2)
op = fa.finalize()
em, estd = _stats(fa.slice_fluctuation(0), samples)
......@@ -148,17 +148,14 @@ def test_complicated_vs_simple(seed, domain):
(loglogavgslope_mean, loglogavgslope_stddev),
prefix=prefix,
harmonic_partner=hspace)
cfm = ift.CorrelatedFieldMaker.make(offset_mean, offset_std_mean,
offset_std_std, prefix)
cfm = ift.CorrelatedFieldMaker.make(offset_mean,
(offset_std_mean, offset_std_std),
prefix)
cfm.add_fluctuations(domain,
fluctuations_mean,
fluctuations_stddev,
flexibility_mean,
flexibility_stddev,
asperity_mean,
asperity_stddev,
loglogavgslope_mean,
loglogavgslope_stddev,
(fluctuations_mean, fluctuations_stddev),
(flexibility_mean, flexibility_stddev),
(asperity_mean, asperity_stddev),
(loglogavgslope_mean, loglogavgslope_stddev),
prefix='',
harmonic_partner=hspace)
inp = ift.from_random(scf.domain)
......
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