def test_merge_linked(): "Check that that merge works correctly for models with linked parameters" submodel1 = dl.dd_gauss submodel2 = dl.dd_gauss2 submodel2 = dl.link(submodel2, mean=['mean1', 'mean2'], width=['width1', 'width2']) x = np.linspace(0, 10, 100) ref1 = submodel1(x, 3, 0.2) ref2 = submodel1(x, 4, 0.3) # Create a global model model = dl.merge(submodel1, submodel2, addweights=True) response = model(x, x, mean_1=3, width_1=0.2, mean_2=4, width_2=0.3, amp1_2=1, amp2_2=1, scale_1=1, weight_1=1, weight_2=1) assert all( [np.allclose(response[n], ref) for n, ref in enumerate([ref1, ref2])])
def test_globalmodel(): "Check the profiling works with multiple datasets" r = np.linspace(2, 6, 300) sigma = 0.1 modelA = deepcopy(dd_gauss) modelB = deepcopy(dd_gauss) model = merge(modelA, modelB) model = link(model, mean=['mean_1', 'mean_2'], width=['width_1', 'width_2']) y = model(r, r, mean=3, width=0.2, scale_1=1, scale_2=1) y[0] += whitegaussnoise(r, sigma, seed=1) y[1] += whitegaussnoise(r, sigma, seed=1) profuq = profile_analysis(model, y, r, r, samples=3, noiselvl=sigma) x, pdf = profuq['mean'].pardist() mean_mean = x[np.argmax(pdf)] x, pdf = profuq['width'].pardist() width_mean = x[np.argmax(pdf)] assert np.allclose([mean_mean, width_mean], [3, 0.2], rtol=1e-2)
# Put the datasets into lists ts = [t1,t2] Vs = [Vexp1,Vexp2] # Normalize the datasets Vs = [V/np.max(V) for V in Vs] # Distance vector r = np.linspace(2,5,150) # nm # Construct the dipolar models for the individual signals V1model = dl.dipolarmodel(ts[0],r) V2model = dl.dipolarmodel(ts[1],r) # Make the global model by joining the individual models globalmodel = dl.merge(V1model,V2model) # Link the distance distribution into a global parameter globalmodel = dl.link(globalmodel,P=['P_1','P_2']) # Fit the model to the data fit = dl.fit(globalmodel,Vs) # %% plt.figure(figsize=[10,7]) violet = '#4550e6' for n in range(len(fit.model)): # Extract fitted dipolar signal Vfit = fit.model[n]
L = [0.3, 3, 10, 30, 300] # µM # Distance vector r = np.linspace(1.5, 6, 90) # Construct a non-parametric distance distribution that is a # linear combination of two non-parametric distributions PAmodel = dl.freedist(r) PBmodel = dl.freedist(r) Pmodel = dl.lincombine(PAmodel, PBmodel, addweights=True) # Construct the dipolar models of the individual signals Vmodels = [dl.dipolarmodel(t, r, Pmodel) for t in ts] # Create the global model titrmodel = dl.merge(*Vmodels) # Make the two components of the distance distriution global titrmodel = dl.link(titrmodel, PA=['P_1_1', 'P_1_2', 'P_1_3', 'P_1_4', 'P_1_5'], PB=['P_2_1', 'P_2_2', 'P_2_3', 'P_2_4', 'P_2_5']) # Functionalize the chemical equilibrium model titrmodel.addnonlinear('Kdis', lb=3, ub=7, par0=5, description='Dissociation constant') titrmodel = dl.relate(titrmodel, weight_2_1=lambda weight_1_1: 1 - weight_1_1, weight_1_1=lambda Kdis: chemicalequilibrium(Kdis, L[0]),
t5p, V5p = np.load('../data/example_5pdeer_#2.npy') # Since they have different scales, normalize both datasets V4p = V4p / np.max(V4p) V5p = V5p / np.max(V5p) # Run fit r = np.linspace(2, 4.5, 100) # Construct the individual dipolar signal models V4pmodel = dl.dipolarmodel(t4p, r, npathways=1) V5pmodel = dl.dipolarmodel(t5p, r, npathways=2) V5pmodel.reftime2.set(lb=3, ub=3.5, par0=3.2) # Make the joint model with the distribution as a global parameters globalmodel = dl.merge(V4pmodel, V5pmodel) globalmodel = dl.link(globalmodel, P=['P_1', 'P_2']) # Fit the model to the data (with fixed regularization parameter) fit = dl.fit(globalmodel, [V4p, V5p], regparam=0.5) # %% plt.figure(figsize=[10, 7]) violet = '#4550e6' # Extract fitted distance distribution Pfit = fit.P scale = np.trapz(Pfit, r) Pci95 = fit.PUncert.ci(95) / scale Pci50 = fit.PUncert.ci(50) / scale
reftime2=['reftime2_1', 'reftime2_2'], lam1=['lam1_1', 'lam1_2'], lam2=['lam2_1', 'lam2_2']) # Make the second weight dependent on the first one Vmodel = dl.relate(Vmodel, weight_2=lambda weight_1: 1 - weight_1) return Vmodel, Vdis_model, Vld_model #---------------------------------------------------------------------------------- # Generate the models Vmodel1, Vdismodel1, Vldmodel1 = dropletmodel(ts[0]) Vmodel2, Vdismodel2, Vldmodel2 = dropletmodel(ts[1]) # Create the global model globalModel = dl.merge(Vmodel1, Vmodel2) # Link global parameters toghether with new names globalModel = dl.link(globalModel, eta=['weight_1_1', 'weight_1_2'], kdis=['decay_1_1', 'decay_1_2'], kld=['decay_2_1', 'decay_2_2'], Dld=['stretch_2_1', 'stretch_2_2'], rmean_dis=['mean_1_1', 'mean_1_2'], rmean_ld=['mean_2_1', 'mean_2_2'], width_dis=['width_1_1', 'width_1_2'], width_ld=['width_2_1', 'width_2_2'], lam1=['lam1_1', 'lam1_2'], lam2=['lam2_1', 'lam2_2'], reftime1=['reftime1_1', 'reftime1_2']) # Specify parameter boundaries and initial conditions
# Set the parameter boundaries and start values Pmodel.meanA.set(lb=2, ub=7, par0=5) Pmodel.meanB.set(lb=2, ub=7, par0=3) Pmodel.widthA.set(lb=0.05, ub=0.8, par0=0.1) Pmodel.widthB.set(lb=0.05, ub=0.8, par0=0.1) Pmodel.fracA.set(lb=0, ub=1, par0=0.5) # Generate the individual dipolar signal models Nsignals = len(Vexps) Vmodels = [[]] * Nsignals for n in range(Nsignals): Vmodels[n] = dl.dipolarmodel(ts[n], r, Pmodel) Vmodels[n].reftime.set(lb=0, ub=0.5, par0=0.2) # Combine the individual signal models into a single global models globalmodel = dl.merge(*Vmodels) # Link the global parameters toghether globalmodel = dl.link(globalmodel, meanA=['meanA_1', 'meanA_2', 'meanA_3'], meanB=['meanB_1', 'meanB_2', 'meanB_3'], widthA=['widthA_1', 'widthA_2', 'widthA_3'], widthB=['widthB_1', 'widthB_2', 'widthB_3']) # Fit the datasets to the model globally fit = dl.fit(globalmodel, Vexps) # Extract the fitted fractions fracAfit = [fit.fracA_1, fit.fracA_2, fit.fracA_3] fracBfit = [1 - fit.fracA_1, 1 - fit.fracA_2, 1 - fit.fracA_3] plt.figure(figsize=(10, 8))