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)
def dropletmodel(t): #---------------------------------------------------------------------------------- # Dispersed-state component model Vdis_model = dl.dipolarmodel(t, r, Pmodel=dl.dd_gauss, Bmodel=dl.bg_exp, npathways=2) # Liquid-droplet-state component model Vld_model = dl.dipolarmodel(t, r, Pmodel=dl.dd_gauss, Bmodel=dl.bg_strexp, npathways=2) # Create a dipolar signal model that is a linear combination of both components Vmodel = dl.lincombine(Vdis_model, Vld_model, addweights=True) Vmodel = dl.link(Vmodel, reftime1=['reftime1_1', 'reftime1_2'], 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
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] Vci = fit.modelUncert[n].ci(95) # Extract fitted distance distribution
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]), weight_2_2=lambda weight_1_2: 1 - weight_1_2, weight_1_2=lambda Kdis: chemicalequilibrium(Kdis, L[1]), weight_2_3=lambda weight_1_3: 1 - weight_1_3,
#---------------------------------------------------------------------------------- # 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 globalModel.eta.set(lb=0.468, ub=0.57, par0=0.520) globalModel.kdis.set(lb=0.0, ub=0.09, par0=0.01) globalModel.kld.set(lb=0.0, ub=1, par0=0.12) globalModel.Dld.set(lb=2, ub=4, par0=2.5) globalModel.rmean_dis.set(lb=3, ub=6.35, par0=3.7) globalModel.rmean_ld.set(lb=1, ub=8, par0=2.6) globalModel.width_dis.set(lb=0.25, ub=0.74, par0=0.44) globalModel.width_ld.set(lb=0.2, ub=2, par0=0.7)
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)) for i in range(Nsignals): # Get the fitted signals and confidence bands Vfit = fit.model[i]