def test_repr_transform(self): p = Transform(None) q = eval(repr(p)) assert p.form == q.form p = Transform("logY") q = eval(repr(p)) assert p.form == q.form
def test_repr_transform(self): p = Transform(None) q = eval(repr(p)) assert (p.form == q.form) p = Transform('logY') q = eval(repr(p)) assert (p.form == q.form)
def setup(): # load the data. DATASET_NAME = os.path.join(refnx.__path__[0], 'analysis', 'test', 'c_PLP0011859_q.txt') # load the data data = ReflectDataset(DATASET_NAME) # the materials we're using si = SLD(2.07, name='Si') sio2 = SLD(3.47, name='SiO2') film = SLD(2, name='film') d2o = SLD(6.36, name='d2o') structure = si | sio2(30, 3) | film(250, 3) | d2o(0, 3) structure[1].thick.setp(vary=True, bounds=(15., 50.)) structure[1].rough.setp(vary=True, bounds=(1., 6.)) structure[2].thick.setp(vary=True, bounds=(200, 300)) structure[2].sld.real.setp(vary=True, bounds=(0.1, 3)) structure[2].rough.setp(vary=True, bounds=(1, 6)) model = ReflectModel(structure, bkg=9e-6, scale=1.) model.bkg.setp(vary=True, bounds=(1e-8, 1e-5)) model.scale.setp(vary=True, bounds=(0.9, 1.1)) model.threads = 1 # fit on a logR scale, but use weighting objective = Objective(model, data, transform=Transform('logY'), use_weights=True) return objective
def setup_method(self): self.pth = os.path.dirname(os.path.abspath(__file__)) self.si = SLD(2.07, name='Si') self.sio2 = SLD(3.47, name='SiO2') self.d2o = SLD(6.36, name='d2o') self.h2o = SLD(-0.56, name='h2o') self.cm3 = SLD(3.5, name='cm3') self.polymer = SLD(2, name='polymer') self.sio2_l = self.sio2(40, 3) self.polymer_l = self.polymer(200, 3) self.structure = (self.si | self.sio2_l | self.polymer_l | self.d2o(0, 3)) fname = os.path.join(self.pth, 'c_PLP0011859_q.txt') self.dataset = ReflectDataset(fname) self.model = ReflectModel(self.structure, bkg=2e-7) self.objective = Objective(self.model, self.dataset, use_weights=False, transform=Transform('logY')) self.global_objective = GlobalObjective([self.objective])
def _on_plot_type_changed(self, change): """ User would like to plot and fit as logR/linR/RQ4/RQ2, etc """ self.transform = Transform(change["new"]) if self.objective is not None: self.objective.transform = self.transform if self.dataset is not None: yt, _ = self.transform(self.dataset.x, self.dataset.y) self.data_plot.set_xdata(self.dataset.x) self.data_plot.set_ydata(yt) self.update_model(None) # probably have to change LHS axis of the data plot when # going between different plot types. if change["new"] == "logY": self.ax_data.set_yscale("linear") else: self.ax_data.set_yscale("log") self.ax_data.relim() self.ax_data.autoscale_view() self.fig.canvas.draw()
def test_globalfitting(self): # smoke test for can the global fitting run? # also tests that global fitting gives same output as # normal fitting (for a single dataset) self.model.scale.setp(vary=True, bounds=(0.1, 2)) self.model.bkg.setp(vary=True, bounds=(1e-10, 8e-6)) self.structure[-1].rough.setp(vary=True, bounds=(0.2, 6)) self.sio2_l.thick.setp(vary=True, bounds=(0.2, 80)) self.polymer_l.thick.setp(bounds=(0.01, 400), vary=True) self.polymer_l.sld.real.setp(vary=True, bounds=(0.01, 4)) self.objective.transform = Transform('logY') starting = np.array(self.objective.parameters) with np.errstate(invalid='raise'): g = CurveFitter(self.global_objective) res_g = g.fit() # need the same starting point self.objective.setp(starting) f = CurveFitter(self.objective) res_f = f.fit() # individual and global should give the same fit. assert_almost_equal(res_g.x, res_f.x)
def test_parallel_objective(self): # check that a parallel objective works without issue # (it could be possible that parallel evaluation fails at a higher # level in e.g. emcee or in scipy.optimize.differential_evolution) model = self.model361 model.threads = 2 objective = Objective( model, (self.qvals361, self.rvals361, self.evals361), transform=Transform("logY"), ) p0 = np.array(objective.varying_parameters()) cov = objective.covar() walkers = np.random.multivariate_normal(np.atleast_1d(p0), np.atleast_2d(cov), size=(100)) map_logl = np.array(list(map(objective.logl, walkers))) map_chi2 = np.array(list(map(objective.chisqr, walkers))) wf = Wrapper_fn2(model.model, p0) map_mod = np.array(list(map(wf, walkers))) with MapWrapper(2) as g: mapw_mod = g(wf, walkers) mapw_logl = g(objective.logl, walkers) mapw_chi2 = g(objective.chisqr, walkers) assert_allclose(mapw_logl, map_logl) assert_allclose(mapw_chi2, map_chi2) assert_allclose(mapw_mod, map_mod)
def test_reflectivity_fit(self): # a smoke test to make sure the reflectivity fit proceeds model = self.model361 objective = Objective(model, (self.qvals361, self.rvals361, self.evals361), transform=Transform('logY')) fitter = CurveFitter(objective) with np.errstate(invalid='raise'): fitter.fit('differential_evolution')
def test_residuals(self): # weighted, with and without transform assert_almost_equal(self.objective.residuals(), (self.data.y - self.mod) / self.data.y_err) objective = Objective(self.model, self.data, transform=Transform('lin')) assert_almost_equal(objective.residuals(), (self.data.y - self.mod) / self.data.y_err) # unweighted, with and without transform objective = Objective(self.model, self.data, use_weights=False) assert_almost_equal(objective.residuals(), self.data.y - self.mod) objective = Objective(self.model, self.data, use_weights=False, transform=Transform('lin')) assert_almost_equal(objective.residuals(), self.data.y - self.mod)
def test_transform(self): pth = os.path.dirname(os.path.abspath(__file__)) fname = os.path.join(pth, 'c_PLP0011859_q.txt') data = ReflectDataset(fname) t = Transform('logY') yt, et = t(data.x, data.y, y_err=data.y_err) assert_equal(yt, np.log10(data.y)) yt, _ = t(data.x, data.y, y_err=None) assert_equal(yt, np.log10(data.y)) EPy, EPe = EP.EPlog10(data.y, data.y_err) assert_equal(yt, EPy) assert_equal(et, EPe)
def test_code_fragment(self): e361 = ReflectDataset(os.path.join(self.pth, "e361r.txt")) si = SLD(2.07, name="Si") sio2 = SLD(3.47, name="SiO2") d2o = SLD(6.36, name="D2O") polymer = SLD(1, name="polymer") # e361 is an older dataset, but well characterised self.structure361 = si | sio2(10, 4) | polymer(200, 3) | d2o(0, 3) self.model361 = ReflectModel(self.structure361, bkg=2e-5) self.model361.scale.vary = True self.model361.bkg.vary = True self.model361.scale.range(0.1, 2) self.model361.bkg.range(0, 5e-5) # d2o self.structure361[-1].sld.real.vary = True self.structure361[-1].sld.real.range(6, 6.36) self.structure361[1].thick.vary = True self.structure361[1].thick.range(5, 20) self.structure361[2].thick.vary = True self.structure361[2].thick.range(100, 220) self.structure361[2].sld.real.vary = True self.structure361[2].sld.real.range(0.2, 1.5) objective = Objective(self.model361, e361, transform=Transform("logY")) objective2 = eval(repr(objective)) assert_allclose(objective2.chisqr(), objective.chisqr()) exec(repr(objective)) exec(code_fragment(objective)) # artificially link the two thicknesses together # check that we can reproduce the objective from the repr self.structure361[2].thick.constraint = self.structure361[1].thick fragment = code_fragment(objective) fragment = fragment + "\nobj = objective()\nresult = obj.chisqr()" d = {} # need to provide the globals dictionary to exec, so it can see imports # e.g. https://bit.ly/2RFOF7i (from stackoverflow) exec(fragment, globals(), d) assert_allclose(d["result"], objective.chisqr())
def test_reflectivity_emcee(self): model = self.model361 model.dq = 5. objective = Objective(model, (self.qvals361, self.rvals361, self.evals361), transform=Transform('logY')) fitter = CurveFitter(objective, nwalkers=100) assert_(len(objective.generative().shape) == 1) assert_(len(objective.residuals().shape) == 1) res = fitter.fit('least_squares') res_mcmc = fitter.sample(steps=5, nthin=10, random_state=1, verbose=False) mcmc_val = [mcmc_result.median for mcmc_result in res_mcmc] assert_allclose(mcmc_val, res.x, rtol=0.05)
def test_resolution_speed_comparator(self): fname = os.path.join(self.pth, "c_PLP0011859_q.txt") dataset = ReflectDataset(fname) sio2 = SLD(3.47, name="SiO2") si = SLD(2.07, name="Si") d2o = SLD(6.36, name="D2O") polymer = SLD(2.0, name="polymer") sio2_l = sio2(30, 3) polymer_l = polymer(125, 3) dx = dataset.x_err structure = si | sio2_l | polymer_l | polymer_l | d2o(0, 3) model = ReflectModel(structure, bkg=2e-6, dq_type="constant") objective = Objective(model, dataset, use_weights=False, transform=Transform("logY")) # check that choose_resolution_approach doesn't change state # of model fastest_method = choose_dq_type(objective) assert model.dq_type == "constant" assert_equal(dx, objective.data.x_err) # check that the comparison worked const_time = time.time() for i in range(1000): objective.generative() const_time = time.time() - const_time model.dq_type = "pointwise" point_time = time.time() for i in range(1000): objective.generative() point_time = time.time() - point_time if fastest_method == "pointwise": assert point_time < const_time elif fastest_method == "constant": assert const_time < point_time # check that we could use the function to setup a reflectmodel ReflectModel(structure, bkg=2e-6, dq_type=choose_dq_type(objective))
def test_modelvals_degenerate_layers(self): # try fitting dataset with a deposited layer split into two degenerate # layers fname = os.path.join(self.pth, "c_PLP0011859_q.txt") dataset = ReflectDataset(fname) sio2 = SLD(3.47, name="SiO2") si = SLD(2.07, name="Si") d2o = SLD(6.36, name="D2O") polymer = SLD(2.0, name="polymer") sio2_l = sio2(30, 3) polymer_l = polymer(125, 3) structure = si | sio2_l | polymer_l | polymer_l | d2o(0, 3) polymer_l.thick.setp(value=125, vary=True, bounds=(0, 250)) polymer_l.rough.setp(value=4, vary=True, bounds=(0, 8)) structure[-1].rough.setp(vary=True, bounds=(0, 6)) sio2_l.rough.setp(value=3.16, vary=True, bounds=(0, 8)) model = ReflectModel(structure, bkg=2e-6) objective = Objective(model, dataset, use_weights=False, transform=Transform("logY")) model.scale.setp(vary=True, bounds=(0, 2)) model.bkg.setp(vary=True, bounds=(0, 8e-6)) slabs = structure.slabs() assert_equal(slabs[2, 0:2], slabs[3, 0:2]) assert_equal(slabs[2, 3], slabs[3, 3]) assert_equal(slabs[1, 3], sio2_l.rough.value) f = CurveFitter(objective) f.fit(method="differential_evolution", seed=1, maxiter=3) slabs = structure.slabs() assert_equal(slabs[2, 0:2], slabs[3, 0:2]) assert_equal(slabs[2, 3], slabs[3, 3])
def make_model(names, bs, thicks, roughs, fig_i, data, show=False, mcmc=False): no_layers = len(bs) layers = [] for i in range(no_layers): names.append('layer' + str(i)) for i in range(no_layers): sld = SLD(bs[i], name=names[i]) layers.append(sld(thicks[i], roughs[i])) layers[0].thick.setp(vary=True, bounds=(thicks[i] - 1, thicks[i] + 1)) layers[0].sld.real.setp(vary=True, bounds=(bs[i] - 1, bs[i] + 1)) for layer in layers[1:]: layer.thick.setp(vary=True, bounds=(thicks[i] - 1, thicks[i] + 1)) layer.sld.real.setp(vary=True, bounds=(bs[i] - 1, bs[i] + 1)) layer.rough.setp(vary=True, bounds=(0, 5)) structure = layers[0] for layer in layers[1:]: structure |= layer print(structure) model = ReflectModel(structure, bkg=3e-6, dq=5.0) #model.scale.setp(bounds=(0.6, 1.2), vary=True) #model.bkg.setp(bounds=(1e-9, 9e-6), vary=True) objective = Objective(model, data, transform=Transform('logY')) fitter = CurveFitter(objective) if mcmc: fitter.sample(1000) process_chain(objective, fitter.chain, nburn=300, nthin=100) else: fitter.fit('differential_evolution') print(objective.parameters) if show: plt.figure(fig_i) plt.plot(*structure.sld_profile()) plt.ylabel('SLD /$10^{-6} \AA^{-2}$') plt.xlabel('distance / $\AA$') return structure, fitter, objective, fig_i + 1
def make_model(names, bs, thicks, roughs, fig_i, data, show=False, mcmc=False): extent = sum( thicks[:, 0]) # (float or Parameter) – Total extent of spline region vs = array( bs )[:, 0] #(Sequence of float/Parameter) – the real part of the SLD values of each of the knots. dz = cum_sum( array(thicks[:, 0]) ) #(Sequence of float/Parameter) – the lateral offset between successive knots. print(dz) name = "number of nots " + str(len(names)) #(str) – Name of component component = Spline(extent, vs, dz, name) front = SLD(0) front = front(0, 0) back = SLD(0) back = back(0, 0) structure = front | component | back model = ReflectModel(structure, bkg=3e-6, dq=5.0) objective = Objective(model, data, transform=Transform('logY')) fitter = CurveFitter(objective) fitter.fit('differential_evolution') return structure, fitter, objective, fig_i + 1
def test_globalfitting(self): # smoke test for can the global fitting run? # also tests that global fitting gives same output as # normal fitting (for a single dataset) self.model.scale.setp(vary=True, bounds=(0.1, 2)) self.model.bkg.setp(vary=True, bounds=(1e-10, 8e-6)) self.structure[-1].rough.setp(vary=True, bounds=(0.2, 6)) self.sio2_l.thick.setp(vary=True, bounds=(0.2, 80)) self.polymer_l.thick.setp(bounds=(0.01, 400), vary=True) self.polymer_l.sld.real.setp(vary=True, bounds=(0.01, 4)) self.objective.transform = Transform('logY') with np.errstate(invalid='raise'): g = CurveFitter(self.global_objective) res_g = g.fit(method='differential_evolution', seed=1, maxiter=10) f = CurveFitter(self.objective) res_f = f.fit(method='differential_evolution', seed=1, maxiter=10) # individual and global should give the same fit. Because we use DE # there is no dependence on starting point, so long as we set a # seed. assert_almost_equal(res_g.x, res_f.x)
def getObjective(data, nLayers, bs_contrast_layer=None, contrast_layer=None, limits = None, doMCMC=False, logpExtra=None, onlyStructure=False, both=False, globalObjective=False): if globalObjective: if bs_contrast_layer is None: bs_contrast_layer = 6 if contrast_layer is None: contrast_layer = 1 # print("data, nLayers, bs_contrast_layer=None,\n contrast_layer=None,\nlimits = None, doMCMC=False,\nlogpExtra=None, onlyStructure=False,\nboth=False, globalObjective=False: ", # data, nLayers, bs_contrast_layer, # contrast_layer, # limits, doMCMC, # logpExtra, onlyStructure, # both, globalObjective) air = SLD(0,name="air layer") airSlab = air(10,0) sio2 = SLD(10,name="bottem layer") sio2Slab = sio2(10,0) if limits is None: limits = [350,50,4,6] # maxThick = 350 # lowerThick = 50 # upperThick = maxThick - nLayers*lowerThick # lowerB = 4 # upperB = 6 maxThick = float(limits[0]) lowerThick = limits[1] upperThick = maxThick - nLayers*lowerThick lowerB = limits[2] upperB = limits[3] if globalObjective: thick_contrast_layer=Parameter(maxThick/nLayers, "layer1 thickness") rough_contrast_layer=Parameter(0, "layer0/contrast roughness") sldcontrastA=SLD(5,name="contrast A layer") sldcontrastASlab= sldcontrastA(thick_contrast_layer,rough_contrast_layer) sldcontrastASlab.thick.setp(vary=True, bounds=(lowerThick,upperThick)) sldcontrastASlab.sld.real.setp(vary=True, bounds=(lowerB,upperB)) sldcontrastB=SLD(5,name="contrast B layer") sldcontrastBSlab = sldcontrastB(thick_contrast_layer,rough_contrast_layer) sldcontrastBSlab.thick.setp(vary=True, bounds=(lowerThick,upperThick)) sldcontrastBSlab.sld.real.setp(vary=True, bounds=(lowerB,upperB)) if nLayers>=1 and not globalObjective: sld1 = SLD(5,name="first layer") sld1Slab = sld1(maxThick/nLayers,0) sld1Slab.thick.setp(vary=True, bounds=(lowerThick,upperThick)) sld1Slab.sld.real.setp(vary=True, bounds=(lowerB,upperB)) if nLayers>=2: sld2 = SLD(5,name="second layer") sld2Slab = sld2(maxThick/nLayers,0) sld2Slab.thick.setp(vary=True, bounds=(lowerThick,upperThick)) sld2Slab.sld.real.setp(vary=True, bounds=(lowerB,upperB)) if nLayers>=3: sld3 = SLD(5,name="third layer") sld3Slab = sld3(maxThick/nLayers,0) sld3Slab.thick.setp(vary=True, bounds=(lowerThick,upperThick)) sld3Slab.sld.real.setp(vary=True, bounds=(lowerB,upperB)) if nLayers>=4: sld4 = SLD(5,name="forth layer") sld4Slab = sld4(maxThick/nLayers,0) sld4Slab.thick.setp(vary=True, bounds=(lowerThick,upperThick)) sld4Slab.sld.real.setp(vary=True, bounds=(lowerB,upperB)) # if nLayers>=1: # sld1Slab.thick.setp(vary=True, bounds=(lowerThick,upperThick)) # sld1Slab.sld.real.setp(vary=True, bounds=(lowerB,upperB)) # if nLayers>=2: # sld2Slab.thick.setp(vary=True, bounds=(lowerThick,upperThick)) # sld2Slab.sld.real.setp(vary=True, bounds=(lowerB,upperB)) # if nLayers>=3: # sld3Slab.thick.setp(vary=True, bounds=(lowerThick,upperThick)) # sld3Slab.sld.real.setp(vary=True, bounds=(lowerB,upperB)) # if nLayers>=4: # sld4Slab.thick.setp(vary=True, bounds=(lowerThick,upperThick)) # sld4Slab.sld.real.setp(vary=True, bounds=(lowerB,upperB)) if globalObjective and contrast_layer==1: if nLayers==1: structure1 = airSlab|sldcontrastASlab|sio2Slab structure2 = airSlab|sldcontrastBSlab|sio2Slab if nLayers==2: structure1 = airSlab|sldcontrastASlab|sld2Slab|sio2Slab structure2 = airSlab|sldcontrastBSlab|sld2Slab|sio2Slab if nLayers==3: structure1 = airSlab|sldcontrastASlab|sld2Slab|sld3Slab|sio2Slab structure2 = airSlab|sldcontrastBSlab|sld2Slab|sld3Slab|sio2Slab if nLayers==4: structure1 = airSlab|sldcontrastASlab|sld2Slab|sld3Slab|sld4Slab|sio2Slab structure2 = airSlab|sldcontrastBSlab|sld2Slab|sld3Slab|sld4Slab|sio2Slab if onlyStructure: returns = structure1,structure2 elif both: model1 = ReflectModel(structure1, bkg=3e-6, dq=5.0) model1.scale.setp(bounds=(0.85, 1.2), vary=True) model1.bkg.setp(bounds=(1e-9, 9e-6), vary=True) objective1 = Objective(model1, data[0], transform=Transform('logY'), logp_extra=logpExtra) model2 = ReflectModel(structure2, bkg=3e-6, dq=5.0) model2.scale.setp(bounds=(0.85, 1.2), vary=True) model2.bkg.setp(bounds=(1e-9, 9e-6), vary=True) objective2 = Objective(model2, data[1], transform=Transform('logY'), logp_extra=logpExtra) returns = GlobalObjective([objective1, objective2]), structure1, structure2 print("GlobalObjective and 2 structures") else: model1 = ReflectModel(structure1, bkg=3e-6, dq=5.0) model1.scale.setp(bounds=(0.85, 1.2), vary=True) model1.bkg.setp(bounds=(1e-9, 9e-6), vary=True) objective1 = Objective(model1, data[0], transform=Transform('logY'), logp_extra=logpExtra) model2 = ReflectModel(structure2, bkg=3e-6, dq=5.0) model2.scale.setp(bounds=(0.85, 1.2), vary=True) model2.bkg.setp(bounds=(1e-9, 9e-6), vary=True) objective2 = Objective(model2, data[1], transform=Transform('logY'), logp_extra=logpExtra) returns = GlobalObjective([objective1, objective2]) elif not globalObjective: if nLayers==1: structure = airSlab|sld1Slab|sio2Slab if nLayers==2: structure = airSlab|sld1Slab|sld2Slab|sio2Slab if nLayers==3: structure = airSlab|sld1Slab|sld2Slab|sld3Slab|sio2Slab if nLayers==4: structure = airSlab|sld1Slab|sld2Slab|sld3Slab|sld4Slab|sio2Slab if onlyStructure: returns = structure elif both: model = ReflectModel(structure, bkg=3e-6, dq=5.0) objective = Objective(model, data, transform=Transform('logY'), logp_extra=logpExtra) returns = objective, structure else: model = ReflectModel(structure, bkg=3e-6, dq=5.0) objective = Objective(model, data, transform=Transform('logY'),logp_extra=logpExtra) returns = objective else: print("error contrast layer not at sld1Slab ie contrast_layer!=0") # print(returns) return returns
def getObjective(data, thicknesses, slds, layerNames, logpExtra=None): air = SLD(0, name="air layer") airSlab = air(10, 0) sio2 = SLD(10, name="bottem layer") sio2Slab = sio2(10, 0) # print(" ... ",slds[0].startPoint) if len(layerNames) >= 1: i = 0 sld1 = SLD(float(slds[i].startPoint), name=layerNames[i]) sld1Slab = sld1(thicknesses[i].startPoint, thicknesses[i].roughness) sld1Slab.thick.setp(vary=thicknesses[i].vary, bounds=(thicknesses[i].lower, thicknesses[i].upper)) sld1Slab.sld.real.setp(vary=slds[i].vary, bounds=(slds[i].lower, slds[i].upper)) else: print(layerNames, " : variable 'layerNames' is empty") if len(layerNames) >= 2: i = 1 sld2 = SLD(slds[i].startPoint, name=layerNames[i]) sld2Slab = sld2(thicknesses[i].startPoint, thicknesses[i].roughness) sld2Slab.thick.setp(vary=thicknesses[i].vary, bounds=(thicknesses[i].lower, thicknesses[i].upper)) sld2Slab.sld.real.setp(vary=slds[i].vary, bounds=(slds[i].lower, slds[i].upper)) if len(layerNames) >= 3: i = 2 sld3 = SLD(slds[i].startPoint, name=layerNames[i]) sld3Slab = sld3(thicknesses[i].startPoint, thicknesses[i].roughness) sld3Slab.thick.setp(vary=thicknesses[i].vary, bounds=(thicknesses[i].lower, thicknesses[i].upper)) sld3Slab.sld.real.setp(vary=slds[i].vary, bounds=(slds[i].lower, slds[i].upper)) if len(layerNames) >= 4: i = 3 sld4 = SLD(slds[i].startPoint, name=layerNames[i]) sld4Slab = sld4(thicknesses[i].startPoint, thicknesses[i].roughness) sld4Slab.thick.setp(vary=thicknesses[i].vary, bounds=(thicknesses[i].lower, thicknesses[i].upper)) sld4Slab.sld.real.setp(vary=slds[i].vary, bounds=(slds[i].lower, slds[i].upper)) if len(layerNames) == 1: structure = airSlab | sld1Slab | sio2Slab if len(layerNames) == 2: structure = airSlab | sld1Slab | sld2Slab | sio2Slab if len(layerNames) == 3: structure = airSlab | sld1Slab | sld2Slab | sld3Slab | sio2Slab if len(layerNames) == 4: structure = airSlab | sld1Slab | sld2Slab | sld3Slab | sld4Slab | sio2Slab model = ReflectModel(structure, bkg=3e-6, dq=5.0) objective = Objective(model, data, transform=Transform('logY'), logp_extra=logpExtra) return objective, structure
def __init__(self): # attributes for the graph # for the graph self.qmin = 0.005 self.qmax = 0.5 self.qpnt = 1000 self.fig = None self.ax_data = None self.ax_residual = None self.ax_sld = None # gridspecs specify how the plots are laid out. Gridspec1 is when the # residuals plot is displayed. Gridspec2 is when it's not visible self._gridspec1 = gridspec.GridSpec(2, 2, height_ratios=[5, 1], width_ratios=[1, 1], hspace=0.01) self._gridspec2 = gridspec.GridSpec(1, 2) self.theoretical_plot = None self.theoretical_plot_sld = None # attributes for a user dataset self.dataset = None self.objective = None self._curvefitter = None self.data_plot = None self.residuals_plot = None self.data_plot_sld = None self.dataset_name = widgets.Text(description="dataset:") self.dataset_name.disabled = True self.chisqr = widgets.FloatText(description="chi-squared:") self.chisqr.disabled = True # fronting slab0 = Slab(0, 0, 0) slab1 = Slab(25, 3.47, 3) slab2 = Slab(0, 2.07, 3) structure = slab0 | slab1 | slab2 rename_params(structure) self.model = ReflectModel(structure) structure = slab0 | slab1 | slab2 self.model = ReflectModel(structure) # give some default parameter limits self.model.scale.bounds = (0.1, 2) self.model.bkg.bounds = (1e-8, 2e-5) self.model.dq.bounds = (0, 20) for slab in self.model.structure: slab.thick.bounds = (0, 2 * slab.thick.value) slab.sld.real.bounds = (0, 2 * slab.sld.real.value) slab.sld.imag.bounds = (0, 2 * slab.sld.imag.value) slab.rough.bounds = (0, 2 * slab.rough.value) # the main GUI widget self.display_box = widgets.VBox() self.tab = widgets.Tab() self.tab.set_title(0, "Model") self.tab.set_title(1, "Limits") self.tab.set_title(2, "Options") self.tab.observe(self._on_tab_changed, names="selected_index") # an output area for messages. self.output = widgets.Output() # options tab self.plot_type = widgets.Dropdown( options=["lin", "logY", "YX4", "YX2"], value="lin", description="Plot Type:", disabled=False, ) self.plot_type.observe(self._on_plot_type_changed, names="value") self.use_weights = widgets.RadioButtons( options=["Yes", "No"], value="Yes", description="use dataset weights?", style={"description_width": "initial"}, ) self.use_weights.observe(self._on_use_weights_changed, names="value") self.transform = Transform("lin") self.display_residuals = widgets.Checkbox( value=False, description="Display residuals") self.display_residuals.observe(self._on_display_residuals_changed, names="value") self.model_view = None self.set_model(self.model)
# In[ ]: model_lipid_1 = ReflectModel(structure_lipid_1) model_lipid_1.scale.setp(vary=True, bounds=(0.005, 10)) model_lipid_1.bkg.setp(dataset_1.y[-2], vary=False) model_lipid_2 = ReflectModel(structure_lipid_2) model_lipid_2.scale.setp(vary=True, bounds=(0.005, 10)) model_lipid_2.bkg.setp(dataset_2.y[-2], vary=False) # The global objective fitting object is defined and the fitting and MCMC performed. # In[ ]: # building the global objective objective_n1 = Objective(model_lipid_1, dataset_1, transform=Transform('YX4')) objective_n2 = Objective(model_lipid_2, dataset_2, transform=Transform('YX4')) global_objective = GlobalObjective([objective_n1, objective_n2]) # ## Fitting # # The differential evolution algorithm is used to find optimal parameters, before the MCMC algorithm probes the parameter space for 1000 steps. # In[ ]: # A differential evolution algorithm is used to obtain an best fit fitter = CurveFitter(global_objective) # A seed is used to ensure reproduciblity res = fitter.fit('differential_evolution', seed=1) # The first 200*200 samples are binned
model_lipid2 = ReflectModel(structure_lipid2) model_lipid2.scale.setp(vary=True, bounds=(0.005, 10)) model_lipid2.bkg.setp(dataset2.y[-1], vary=False) model_lipid3 = ReflectModel(structure_lipid3) model_lipid3.scale.setp(vary=True, bounds=(0.005, 10)) model_lipid3.bkg.setp(dataset3.y[-1], vary=False) model_lipid4 = ReflectModel(structure_lipid4) model_lipid4.scale.setp(vary=True, bounds=(0.005, 10)) model_lipid4.bkg.setp(dataset4.y[-1], vary=False) models = [model_lipid1, model_lipid2, model_lipid3, model_lipid4] objective1 = Objective(model_lipid1, dataset1, transform=Transform('YX4')) objective2 = Objective(model_lipid2, dataset2, transform=Transform('YX4')) objective3 = Objective(model_lipid3, dataset3, transform=Transform('YX4')) objective4 = Objective(model_lipid4, dataset4, transform=Transform('YX4')) global_objective = GlobalObjective( [objective1, objective2, objective3, objective4]) # The chain is read in by refnx, and processed to assigned it to the global objective. # In[8]: chain = refnx.analysis.load_chain('{}/{}/chain.txt'.format( analysis_dir, lipid)) processed_chain = refnx.analysis.process_chain(global_objective, chain)
hold_phih=True, ) models = [] t = len(cont) for i in range(t): models.append(ReflectModel(structures[i])) models[i].scale.setp(vary=True, bounds=(0.005, 10)) models[i].bkg.setp(datasets[i].y[-1], vary=True, bounds=(1e-4, 1e-10)) objectives = [] t = len(cont) for i in range(t): objectives.append( Objective(models[i], datasets[i], transform=Transform("YX4"))) global_objective = GlobalObjective(objectives) chain = refnx.analysis.load_chain("{}_chain.txt".format(anal_dir)) pchain = refnx.analysis.process_chain(global_objective, chain) para_labels = [ '_scale_{}_{}'.format(sp, cont[0]), '_bkg_{}_{}'.format(sp, cont[0]), '-d_h_{}'.format(sp), '-d_t_{}'.format(sp), '_rough_{}'.format(sp), '_scale_{}_{}'.format(sp, cont[1]), '_bkg_{}_{}'.format(sp, cont[1]), '_scale_{}_{}'.format(sp, cont[2]), '_bkg_{}_{}'.format(sp, cont[2]), '_scale_{}_{}'.format(sp, cont[3]), '_bkg_{}_{}'.format(sp, cont[3]), '_scale_{}_{}'.format(sp, cont[4]), '_bkg_{}_{}'.format(sp, cont[4]), '_scale_{}_{}'.format(sp, cont[5]), '_bkg_{}_{}'.format(sp, cont[5]),
structure = si | sio2(30, 3) | film(250, 3) | d2o(0, 3) structure[1].thick.setp(vary=True, bounds=(15., 50.)) structure[1].rough.setp(vary=True, bounds=(1., 6.)) structure[2].thick.setp(vary=True, bounds=(200, 300)) structure[2].sld.real.setp(vary=True, bounds=(0.1, 3)) structure[2].rough.setp(vary=True, bounds=(1, 6)) model = ReflectModel(structure, bkg=9e-6, scale=1.) model.bkg.setp(vary=True, bounds=(1e-8, 1e-5)) model.scale.setp(vary=True, bounds=(0.9, 1.1)) # fit on a logR scale, but use weighting objective = Objective(model, data, transform=Transform('logY'), use_weights=True) # create the fit instance fitter = CurveFitter(objective) # do the fit res = fitter.fit(method='differential_evolution') # see the fit results print(objective) fig = plt.figure() ax = fig.add_subplot(2, 1, 1) ax.scatter(data.x, data.y, label=DATASET_NAME) ax.semilogy()
def getObjective(data, nLayers, limits=None, doMCMC=False, fitDq=False, logpExtra=None, onlyStructure=False, both=False): air = SLD(0, name="air layer") airSlab = air(10, 0) sio2 = SLD(10, name="bottem layer") sio2Slab = sio2(10, 0) if limits is None: limits = [350, 50, 4, 6] # maxThick = 350 # lowerThick = 50 # upperThick = maxThick - nLayers*lowerThick # lowerB = 4 # upperB = 6 maxThick = float(limits[0]) lowerThick = limits[1] upperThick = maxThick - nLayers * lowerThick lowerB = limits[2] upperB = limits[3] if nLayers >= 1: sld1 = SLD(5, name="first layer") sld1Slab = sld1(maxThick / nLayers, 0) if nLayers >= 2: sld2 = SLD(5, name="second layer") sld2Slab = sld2(maxThick / nLayers, 0) if nLayers >= 3: sld3 = SLD(5, name="second layer") sld3Slab = sld3(maxThick / nLayers, 0) if nLayers >= 4: sld4 = SLD(5, name="second layer") sld4Slab = sld4(maxThick / nLayers, 0) if nLayers >= 1: sld1Slab.thick.setp(vary=True, bounds=(lowerThick, upperThick)) sld1Slab.sld.real.setp(vary=True, bounds=(lowerB, upperB)) if nLayers >= 2: sld2Slab.thick.setp(vary=True, bounds=(lowerThick, upperThick)) sld2Slab.sld.real.setp(vary=True, bounds=(lowerB, upperB)) if nLayers >= 3: sld3Slab.thick.setp(vary=True, bounds=(lowerThick, upperThick)) sld3Slab.sld.real.setp(vary=True, bounds=(lowerB, upperB)) if nLayers >= 4: sld4Slab.thick.setp(vary=True, bounds=(lowerThick, upperThick)) sld4Slab.sld.real.setp(vary=True, bounds=(lowerB, upperB)) if nLayers == 1: structure = airSlab | sld1Slab | sio2Slab if nLayers == 2: structure = airSlab | sld1Slab | sld2Slab | sio2Slab if nLayers == 3: structure = airSlab | sld1Slab | sld2Slab | sld3Slab | sio2Slab if nLayers == 4: structure = airSlab | sld1Slab | sld2Slab | sld3Slab | sld4Slab | sio2Slab if onlyStructure: returns = structure elif both: model = ReflectModel(structure, bkg=3e-6, dq=5.0) if fitDq: model.dq.setp(vary=True, bounds=(0., 10.)) objective = Objective(model, data, transform=Transform('logY'), logp_extra=logpExtra) returns = objective, structure else: model = ReflectModel(structure, bkg=3e-6, dq=5.0) if fitDq: model.dq.setp(vary=True, bounds=(0., 10.)) objective = Objective(model, data, transform=Transform('logY'), logp_extra=logpExtra) returns = objective return returns
lipid_2.thick_heads.constraint = lipid_1.thick_heads structure_lipid_2[-1].rough.constraint = structure_lipid_1[-1].rough model_lipid1 = ReflectModel(structure_lipid_1) model_lipid1.scale.setp(vary=True, bounds=(0.005, 10)) model_lipid1.bkg.setp(dataset1.y[-2], vary=False) model_lipid2 = ReflectModel(structure_lipid_2) model_lipid2.scale.setp(vary=True, bounds=(0.005, 10)) model_lipid2.bkg.setp(dataset2.y[-2], vary=False) models = [model_lipid1, model_lipid2] structures = [structure_lipid_1, structure_lipid_2] # building the global objective objective_n1 = Objective(model_lipid1, dataset1, transform=Transform('YX4')) objective_n2 = Objective(model_lipid2, dataset2, transform=Transform('YX4')) global_objective = GlobalObjective([objective_n1, objective_n2]) # The chain is read in by refnx, and processed to assigned it to the global objective. # In[ ]: chain = refnx.analysis.load_chain('{}/{}/{}_chain_neutron.txt'.format( analysis_dir, lipid, sp)) processed_chain = refnx.analysis.process_chain(global_objective, chain) # The global objective is printed to check it is accurate.
def global_fitter_setup(global_pilot_file, dqvals=5.0): # Parse the global_fitter setup from Igor. # TODO deal with user generated non-slab models. with open(global_pilot_file, 'r') as f: data_files = f.readline().split() pilot_files = f.readline().split() constraints = np.loadtxt(global_pilot_file, skiprows=2, dtype=int) # open the datafiles datasets = [] for data_file in data_files: dataset = ReflectDataset(data_file) datasets.append(dataset) # deal with the individual pilot files parameters = [] for pilot_file in pilot_files: pars = np.loadtxt(pilot_file, skiprows=4) # lets just assume for now that the data has resolution info # and that we're doing a slab model. pv = pars[:, 0][:] varies = (pars[:, 1].astype(int) == 0) # workout bounds, and account for the fact that MotofitMPI # doesn't set bounds for parameters that are fixed bounds = [] for idx in range(np.size(pv)): if not varies[idx]: bounds.append((0, 2 * pv[idx])) else: bounds.append(pars[idx, 2:4]) P = to_parameters(pv, varies=varies, bounds=bounds) parameters.append(P) # now create CurveFitting instances T = Transform('logY') fitters = [] for parameter, dataset in zip(parameters, datasets): t_data_y, t_data_yerr = T.transform(dataset.x, dataset.y, dataset.y_err) if isinstance(dqvals, numbers.Real): _dqvals = float(dqvals) else: _dqvals = dataset.x_err c = CurveFitter(ReflectivityFitFunction(T.transform, workers=True), (dataset.x, t_data_y, t_data_yerr), parameter, fcn_kws={'dqvals': _dqvals}) fitters.append(c) # create globalfitter # setup constraints unique, indices = np.unique(constraints, return_index=True) # TODO assertions for checking linkage integrity n_datasets = len(datasets) def is_unique(row, col): ravelled_idx = row * n_datasets + col return ravelled_idx in indices cons = [] for col in range(n_datasets): for row in range(len(parameters[col])): if constraints[row, col] == -1 or is_unique(row, col): continue # so it's not unique, but which parameter does it depend on? # find location of master parameter master = np.extract(unique == constraints[row, col], indices)[0] m_col = master % n_datasets m_row = (master - m_col) // n_datasets constraint = 'd%u:p%u = d%u:p%u' % (col, row, m_col, m_row) cons.append(constraint) # also have to rejig the bounds because MotoMPI doesn't # set bounds for those that aren't unique. But this is bad for # lmfit because it'll clip them. par = fitters[col].params['p%u' % row] m_par = fitters[m_col].params['p%u' % m_row] par.min = m_par.min par.max = m_par.max global_fitter = GlobalFitter(fitters, constraints=cons) # # update the constraints # global_fitter.params.update_constraints() return global_fitter
def test_transform_pickle(self): # can you pickle the Transform object? pkl = pickle.dumps(Transform('logY')) pickle.loads(pkl)
def global_fitter_setup(global_pilot_file, dqvals=5.0): # Parse the global_fitter setup from Igor. # TODO deal with user generated non-slab models. with open(global_pilot_file, 'r') as f: data_files = f.readline().split() pilot_files = f.readline().split() constraints = np.loadtxt(global_pilot_file, skiprows=2, dtype=int) # open the datafiles datasets = [] for data_file in data_files: dataset = ReflectDataset(data_file) datasets.append(dataset) # deal with the individual pilot files parameters = [] for pilot_file in pilot_files: pars = np.loadtxt(pilot_file, skiprows=4) # lets just assume for now that the data has resolution info # and that we're doing a slab model. pv = pars[:, 0][:] varies = (pars[:, 1].astype(int) == 0) # workout bounds, and account for the fact that MotofitMPI # doesn't set bounds for parameters that are fixed bounds = [] for idx in range(np.size(pv)): if not varies[idx]: bounds.append((0, 2 * pv[idx])) else: bounds.append(pars[idx, 2:4]) P = to_parameters(pv, varies=varies, bounds=bounds) parameters.append(P) # now create CurveFitting instances T = Transform('logY') fitters = [] for parameter, dataset in zip(parameters, datasets): t_data_y, t_data_yerr = T.transform(dataset.x, dataset.y, dataset.y_err) if isinstance(dqvals, numbers.Real): _dqvals = float(dqvals) else: _dqvals = dataset.x_err c = CurveFitter(ReflectivityFitFunction(T.transform, workers=True), (dataset.x, t_data_y, t_data_yerr), parameter, fcn_kws={'dqvals': _dqvals}) fitters.append(c) # create globalfitter # setup constraints unique, indices = np.unique(constraints, return_index=True) # TODO assertions for checking linkage integrity n_datasets = len(datasets) def is_unique(row, col): ravelled_idx = row * n_datasets + col return ravelled_idx in indices cons = [] for col in range(n_datasets): for row, val in enumerate(parameters[col]): if constraints[row, col] == -1 or is_unique(row, col): continue # so it's not unique, but which parameter does it depend on? # find location of master parameter master = np.extract(unique == constraints[row, col], indices)[0] m_col = master % n_datasets m_row = (master - m_col) // n_datasets constraint = 'd%u:p%u = d%u:p%u' % (col, row, m_col, m_row) cons.append(constraint) # also have to rejig the bounds because MotoMPI doesn't # set bounds for those that aren't unique. But this is bad for # lmfit because it'll clip them. par = fitters[col].params['p%u' % row] m_par = fitters[m_col].params['p%u' % m_row] par.min = m_par.min par.max = m_par.max global_fitter = GlobalFitter(fitters, constraints=cons) # # update the constraints # global_fitter.params.update_constraints() return global_fitter
n = l.reshape(timesteps, sim.layers.shape[1]-layers_to_cut, sim.layers.shape[2]) data_dir = '../data/reflectometry2/dspc_{}/'.format(surface_pressure) dataset = ReflectDataset(os.path.join(data_dir, '{}{}.dat'.format(contrast, surface_pressure))) refy = np.zeros((n.shape[0], dataset.x.size)) sldy = [] chi = np.zeros((n.shape[0])) print(n.shape[0]) for i in range(n.shape[0]): sim.av_layers = n[i, :, :] model = ReflectModel(sim) model.scale.setp(1, vary=True, bounds=(0.00000001, np.inf)) model.bkg.setp(dataset.y[-1], vary=False) objective = Objective(model, dataset, transform=Transform('YX4')) fitter = CurveFitter(objective) res = fitter.fit() refy[i] = model(dataset.x, x_err=dataset.x_err)*(dataset.x)**4 sldy.append(sim.sld_profile()[1]) chi[i] = objective.chisqr() all_chi = np.append(all_chi, objective.chisqr()) if i == 0: ax1.errorbar(dataset.x, dataset.y*(dataset.x)**4 * 10**(ci-1), yerr=dataset.y_err*( dataset.x)**4 * 10**(ci-1), linestyle='', marker='o', color=sns.color_palette()[ci]) if i % 5 == 0: ax1.plot(dataset.x,
def seperateNLayer(data, nLayers, limits = None, doMCMC=False): #used air = SLD(0,name="air layer") airSlab = air(10,0) sio2 = SLD(10,name="bottem layer") sio2Slab = sio2(10,0) if limits is None: limits = [350,50,4,6] # maxThick = 350 # lowerThick = 50 # upperThick = maxThick - nLayers*lowerThick # lowerB = 4 # upperB = 6 maxThick = float(limits[0]) lowerThick = limits[1] upperThick = maxThick - nLayers*lowerThick lowerB = limits[2] upperB = limits[3] if nLayers>=1: sld1 = SLD(5,name="first layer") sld1Slab = sld1(maxThick/nLayers,0) if nLayers>=2: sld2 = SLD(5,name="second layer") sld2Slab = sld2(maxThick/nLayers,0) if nLayers>=3: sld3 = SLD(5,name="second layer") sld3Slab = sld3(maxThick/nLayers,0) if nLayers>=4: sld4 = SLD(5,name="second layer") sld4Slab = sld4(maxThick/nLayers,0) if nLayers>=1: sld1Slab.thick.setp(vary=True, bounds=(lowerThick,upperThick)) sld1Slab.sld.real.setp(vary=True, bounds=(lowerB,upperB)) if nLayers>=2: sld2Slab.thick.setp(vary=True, bounds=(lowerThick,upperThick)) sld2Slab.sld.real.setp(vary=True, bounds=(lowerB,upperB)) if nLayers>=3: sld3Slab.thick.setp(vary=True, bounds=(lowerThick,upperThick)) sld3Slab.sld.real.setp(vary=True, bounds=(lowerB,upperB)) if nLayers>=4: sld4Slab.thick.setp(vary=True, bounds=(lowerThick,upperThick)) sld4Slab.sld.real.setp(vary=True, bounds=(lowerB,upperB)) if nLayers>=1: structure = airSlab|sld1Slab|sio2Slab if nLayers>=2: structure = airSlab|sld1Slab|sld2Slab|sio2Slab if nLayers>=3: structure = airSlab|sld1Slab|sld2Slab|sld3Slab|sio2Slab if nLayers>=4: structure = airSlab|sld1Slab|sld2Slab|sld3Slab|sld4Slab|sio2Slab model = ReflectModel(structure, bkg=3e-6, dq=5.0) objective = Objective(model, data, transform=Transform('logY')) fitter = CurveFitter(objective) if not doMCMC: fitter.fit("differential_evolution") else: fitter.sample(500) fitter.sampler.reset() fitter.sample(40, nthin=50) pass # print(objective.parameters) lp = objective.logpost() # print("log: ", lp) return lp