Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fitparamodel: rename rescale keyword #129

Merged
merged 2 commits into from
Mar 30, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ Release v0.13.0 - March 2021
- Implemented the constraint ``Lam0+sum(lam)<=1`` to ensure the structural-identifiability of ``Lam0`` and ``V0`` during SNLLS optimization of experiment models with more than one modulated dipolar pathway (i.e. does not affect ``ex_4pdeer``) ([#76](https://github.com/JeschkeLab/DeerLab/issues/76),[#108](https://github.com/JeschkeLab/DeerLab/pull/108)).
- ``fitparamodel``:
- Made ``par0`` a positional argument instead of an optional keyword ([#70](https://github.com/JeschkeLab/DeerLab/issues/70)). to avoid errors when not defined ([#69](https://github.com/JeschkeLab/DeerLab/issues/69)).
- Keyword argument ``rescale`` has been renamed to ``fitscale`` ([#128])https://github.com/JeschkeLab/DeerLab/issues/128)).
- ``snlls``:
- Corrected bug that was leading to the smoothness penalty being accounted for twice in the least-squares residual during optimization ([#103](https://github.com/JeschkeLab/DeerLab/issues/103)).
- Now returns the uncertainty quantification of linear and nonlinear parts as separate objects ``nonlinUncert`` and ``linUncert`` ([#108](https://github.com/JeschkeLab/DeerLab/pull/108)).
Expand Down
2 changes: 1 addition & 1 deletion deerlab/correctscale.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ def correctscale(V,t,tmax=[],model='deer'):
raise KeyError("Unknown model '{}'".format(model))

# Run the parametric model fitting
fit = fitparamodel(V_,fitmodel,par0,lb,ub,rescale=False,uq=False)
fit = fitparamodel(V_,fitmodel,par0,lb,ub,fitscale=False,uq=False)

# Get the fitted signal amplitude and scale the signal
V0 = Amp0*fit.param[0]
Expand Down
16 changes: 8 additions & 8 deletions deerlab/fitparamodel.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

def fitparamodel(V, model, par0, lb=None, ub=None, weights=1,
multistart=1, tol=1e-10, maxiter=3000,
rescale=True, uq=True, covmatrix=None):
fitscale=True, uq=True, covmatrix=None):
r""" Fits the dipolar signal(s) to a parametric model using non-linear least-squares.

Parameters
Expand All @@ -36,8 +36,8 @@ def fitparamodel(V, model, par0, lb=None, ub=None, weights=1,
weights : array_like, optional
Array of weighting coefficients for the individual signals in global fitting, the default is all weighted equally.

rescale : boolean, optional
Enable/disable optimization of the signal scale, by default it is enabled.
fitscale : boolean, optional
Enable/disable fitting of the signal scale, by default it is enabled.

multiStarts : scalar, optional
Number of starting points for global optimization, the default is 1.
Expand Down Expand Up @@ -173,23 +173,23 @@ def lsqresiduals(p):
Function that provides vector of residuals, which is the objective
function for the least-squares solvers
"""
nonlocal scales

# Evaluate the model
Vsim = model(p)

# Check if there are invalid values...
if any(np.isnan(Vsim)) or any(np.isinf(Vsim)):
res = np.zeros_like(Vsim) # ...can happen when Jacobian is evaluated outside of bounds
return res

# Otherwise if requested, compute the scale of the signal via linear LSQ
if rescale:
# If requested, fit the scale of the signal via linear LSQ
if fitscale:
nonlocal scales
scales = []
for subset in Vsubsets:
Vsim_,V_ = (V[subset] for V in [Vsim, V]) # Rescale the subsets corresponding to each signal
scale = np.squeeze(np.linalg.lstsq(np.atleast_2d(Vsim_).T,np.atleast_2d(V_).T,rcond=None)[0])
Vsim[subset] = scale*Vsim_
scales.append(scale) # Store the optimized scales of each signal
scales.append(scale) # Store the fitted scales of each signal

# Compute the residual
res = weights*(V-Vsim)
Expand Down
2 changes: 1 addition & 1 deletion examples/plot_emulating_deeranalysis_workflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ def Bmodel(par):
par0 = [0.5, 0.5, 3]
lb = [0.1, 0, 1]
ub = [1, 5, 6]
fit = dl.fitparamodel(V[mask],Bmodel,par0,lb,ub,rescale=False)
fit = dl.fitparamodel(V[mask],Bmodel,par0,lb,ub,fitscale=False)

lamfit,kappa,d = fit.param
Bfit = dl.bg_strexp(t,[kappa,d])
Expand Down
2 changes: 1 addition & 1 deletion examples/plot_extracting_gauss_constraints.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@
ub = info['Upper']

# Fit the Gaussians
fit = dl.fitparamodel(Pfit,Pmodel,par0,lb,ub,covmatrix=Pfit_covmat,rescale=False)
fit = dl.fitparamodel(Pfit,Pmodel,par0,lb,ub,covmatrix=Pfit_covmat,fitscale=False)

# Extract the fit results
parfit = fit.param
Expand Down
6 changes: 3 additions & 3 deletions test/test_fitparamodel.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,8 @@ def test_rescaling():
ub = [20, 5]
mymodel = lambda param: dipolarkernel(t,r)@dd_gauss(r,param)

fit1 = fitparamodel(V*scale,mymodel,par0,lb,ub,rescale=True)
fit2 = fitparamodel(V,mymodel,par0,lb,ub,rescale=False)
fit1 = fitparamodel(V*scale,mymodel,par0,lb,ub,fitscale=True)
fit2 = fitparamodel(V,mymodel,par0,lb,ub,fitscale=False)

assert all(abs(fit1.param - fit2.param) < 1e-2)
# =======================================================================
Expand Down Expand Up @@ -287,7 +287,7 @@ def test_confinter_values():
[1.8953902386010164, 2.322276885466784],
[2.0029218541761944, 2.214745269892137]]

fit = fitparamodel(y,lambda p: p[0]*x + p[1],[0.1,1],rescale=False)
fit = fitparamodel(y,lambda p: p[0]*x + p[1],[0.1,1],fitscale=False)
a_ci = [fit.uncertainty.ci(cov[i])[0,:] for i in range(3)]
b_ci = [fit.uncertainty.ci(cov[i])[1,:] for i in range(3)]

Expand Down