1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
|
"""
Go through each model, vary one parameter and fit it back to the
default value of that model.
"""
import numpy as np
import os
import pycorrfit
from pycorrfit.correlation import Correlation
from pycorrfit.fit import Fit
import pytest
# GLOBAL PARAMETERS FOR THIS TEST:
TAUMIN = 1e-3
TAUMAX = 1e6
TAULEN = 100
FITALG = "Lev-Mar"
def fit_single_parameter(modelid, fullparms, parmid, parmval, noise=False):
"""
Use the full parameter set `fullparms` and leave a single parameter
`parmid` variable during the fit.
Returns the fitted value of the parameter with index `parmid`
"""
corr = Correlation(fit_model=modelid, fit_algorithm=FITALG, verbose=0)
tau = np.exp(np.linspace(np.log(TAUMIN), np.log(TAUMAX), TAULEN))
# Create artificial data by using the current fit_model
data = corr.fit_model(fullparms, tau)
if noise:
if noise is True:
deltanoise = (np.max(data)-np.min(data))/20
else:
deltanoise = (np.max(data)-np.min(data))*noise
anoise = (np.random.random(data.shape[0])-.5)*deltanoise
data += anoise
# Add artificial data to data set
corr.correlation = np.dstack((tau, data))[0]
# Set variable parameters
fit_bool = np.zeros(fullparms.shape[0])
fit_bool[parmid] = True
corr.fit_parameters_variable = fit_bool
fullparms_edit = fullparms.copy()
fullparms_edit[parmid] = parmval
corr.fit_parameters = fullparms_edit
Fit(corr)
return corr.fit_parameters[parmid]
def deviate_parameter(model, parmid):
"""
Returns a deviated version of the parameter with id `parmid`.
Performs model checks to ensure the new value is physical.
"""
val = model.default_values[parmid]
if val == 0:
val += .1
else:
val *= .9
return val
@pytest.mark.filterwarnings('ignore::pycorrfit.fit.StuckParameterWarning')
@pytest.mark.skipif(os.uname().machine == 'mips64',
reason='minor skew on mips causes test failure')
def test_fit_single_parameter():
"""
Deviate a single parameter and fit it back.
"""
allow_fail = [
[6082, "SP"],
]
faillist = list()
for model in pycorrfit.models.models:
fullparms = model.default_values
for ii, val in enumerate(fullparms):
newval = deviate_parameter(model, ii)
fitval = fit_single_parameter(model.id, fullparms, ii,
newval, noise=False)
# print(val-fitval)
if not np.allclose([val], [fitval]):
if not [model.id, model.parameters[0][ii]] in allow_fail:
faillist.append([model.id, model.parameters[0][ii],
val, fitval])
if faillist:
raise ValueError("Model tests failed for:\n", faillist)
def fit_single_parameter_with_noise(noise=0.005):
"""
Deviate a single parameter and fit it back.
"""
faillist = list()
succlist = list()
for model in pycorrfit.models.models:
fullparms = model.default_values
for ii, val in enumerate(fullparms):
newval = deviate_parameter(model, ii)
fitval = fit_single_parameter(model.id, fullparms, ii, newval,
noise=noise)
if not np.allclose([val], [fitval], atol=.1, rtol=.1):
faillist.append([model.id, model.parameters[0][ii],
val, fitval])
else:
succlist.append([model.id, model.parameters[0][ii],
val, fitval])
return succlist, faillist
@pytest.mark.filterwarnings('ignore::pycorrfit.fit.StuckParameterWarning')
@pytest.mark.skipif(os.uname().machine == 'mips64',
reason='minor skew on mips causes test failure')
def test_fit_single_parameter_with_noise_one_permille():
succlist, faillist = fit_single_parameter_with_noise(noise=0.001)
if len(faillist)/len(succlist) > .01:
raise ValueError("Model tests failed for:\n", faillist)
@pytest.mark.filterwarnings('ignore::pycorrfit.fit.StuckParameterWarning')
@pytest.mark.skipif(os.uname().machine == 'mips64',
reason='minor skew on mips causes test failure')
def test_fit_single_parameter_with_noise_two_percent():
succlist, faillist = fit_single_parameter_with_noise(noise=0.02)
if len(faillist)/len(succlist) > .05:
raise ValueError("Model tests failed for:\n", faillist)
@pytest.mark.filterwarnings('ignore::pycorrfit.fit.StuckParameterWarning')
@pytest.mark.skipif(os.uname().machine == 'mips64',
reason='minor skew on mips causes test failure')
def test_fit_single_parameter_with_noise_five_percent():
succlist, faillist = fit_single_parameter_with_noise(noise=0.05)
if len(faillist)/len(succlist) > .10:
raise ValueError("Model tests failed for:\n", faillist)
if __name__ == "__main__":
# Run all tests
loc = locals()
for key in list(loc.keys()):
if key.startswith("test_") and hasattr(loc[key], "__call__"):
loc[key]()
|