def test_manualtransform_arg_model(): ### Creating a SqE model for transformation sqe_arg = SqE_from_arg(T=20.) ### Creating energy, wavelength parameter space lam = sqe_arg.model_params["lam"] dlam = sqe_arg.model_params["dlam"] nlam = 5 #20 ne = 10 #15000 lSD = 3.43 l = linspace(1 - dlam * 1.01, 1 + dlam * 1.01, nlam) * lam ll = tile(l, (ne, 1)) a = -0.99999 * energy_from_lambda(l) ee = linspace(a, 15.0, ne) ### Values for transformation taus = logspace(-6, -1, 101) freqs = MIEZE_DeltaFreq_from_time(taus * 1.0e-9, 3.43, 6.0) mieze_phase = MIEZE_phase(ee, freqs[30], lSD, ll) det_eff = detector_efficiency(ee, ll, 1) tri_distr = triangle_distribution(ll, lam, dlam) print(ll) print(ee) print(mieze_phase) print(det_eff) print(tri_distr)
def test_from_Minuit_and_adjust_it(): ### Creating a SqE model for transformation # We need some lines L1 = LorentzianLine("Lorentzian1", (-5.0, 5.0), x0=0.0, width=0.4, c=0.0, weight=1) L2 = LorentzianLine(name="Lorentzian2", domain=(-5.0, 5.0), x0=1.5, width=0.4, c=0.0, weight=2) # Contruct a SqE model sqe1 = SqE((L1, L2), lam=6.0, dlam=0.12, lSD=3.43, T=20) ### Instantiate a transformer sqt1 = SqtTransformer( sqe1, corrections=( ), #(DetectorEfficiencyCorrectionFactor(sqe1, ne=15000, nlam=20),), ne=10000, nlam=20, lSD=3.43) ### Values for transformation datataus = array([ 2.0e-6, 6.0e-6, 4.1e-5, 2.5e-4, 5.5e-4, 1.0e-3, 1.32e-3, 1.7e-3, 2.2e-3, 2.63e-3, 2.77e-3, 3.3e-3, 4.27e-3, 5.11e-3, 6.77e-3, 8.96e-3, 2.0e-2 ]) x = MIEZE_DeltaFreq_from_time(datataus * 1.0e-9, 3.43, 6.0) ### create artificial data via TRANSFORM!! y = array([sqt1(freq) for freq in x]) yerr = 0.02 * random.randn(len(y)) ### initialize Minuits! m = FitModelCreator.from_transformer(sqt1, x, y + yerr, yerr, [0.45, 0.0, 1.2, -1.5, 0.3, 0.0, 2.2]) m.fixed["c_Lorentzian1"] = True m.fixed["c_Lorentzian2"] = True # Adjust fit behavior -> reinitialize another Minuit obj m2 = FitModelCreator.from_Minuit(minuitobj=m, limit_weight_Lorentzian1=(0, None), limit_width_Lorentzian1=(0, None), limit_weight_Lorentzian2=(0, None), limit_width_Lorentzian2=(0, None), fix_c_Lorentzian1=True, fix_c_Lorentzian2=True)
def test_from_transformer(): ### Creating a SqE model for transformation # We need some lines L1 = LorentzianLine("Lorentzian1", (-5.0, 5.0), x0=0.0, width=0.4, c=0.0, weight=1) L2 = LorentzianLine(name="Lorentzian2", domain=(-5.0, 5.0), x0=1.5, width=0.4, c=0.0, weight=2) L3 = F_ILine("FI1", (-energy_from_lambda(6.0), 15), x0=-0.1, width=0.008, A=350.0, q=0.02, kappa=0.01, c=0.0, weight=1) # Contruct a SqE model sqe1 = SqE((L1, L2, L3), lam=6.0, dlam=0.12, lSD=3.43, T=20) ### Instantiate a transformer sqt1 = SqtTransformer(sqe1, corrections=(DetectorEfficiencyCorrectionFactor( sqe1, ne=10000, nlam=20), ), ne=10000, nlam=20, lSD=3.43) ### Values for transformation datataus = array([ 2.0e-6, 6.0e-6, 4.1e-5, 2.5e-4, 5.5e-4, 1.0e-3, 1.32e-3, 1.7e-3, 2.2e-3, 2.63e-3, 2.77e-3, 3.3e-3, 4.27e-3, 5.11e-3, 6.77e-3, 8.96e-3, 2.0e-2 ]) x = MIEZE_DeltaFreq_from_time(datataus * 1.0e-9, 3.43, 6.0) ### create artificial data via TRANSFORM!! y = array([sqt1(freq) for freq in x]) yerr = 0.02 * random.randn(len(y)) ### instntiate Minuit obj! m = FitModelCreator.from_transformer(sqt1, x, y + yerr, yerr, [ 0.45, 0.0, 1.2, -1.5, 0.3, 0.0, 2.2, -0.5, 0.01, 350.0, 0.02, 0.01, 0.0, 1.0 ])
def test_adaptive_vs_linear(): ### Instantiate a transformer sqtadapt = SqtTransformer.load_from_dict(**STANDARD_SQT.export_to_dict()) sqtlinear = SqtTransformer.load_from_dict(**STANDARD_SQT.export_to_dict()) sqtlinear.update_params(ne=50000, integ_mode="linear") ### Values for transformation taus = logspace(-4, 1, 81) freqs = MIEZE_DeltaFreq_from_time(taus * 1.0e-9, 3.43, 6.0) ### perform transformation from time import time startt = time() adaptvals = array([sqtadapt(freq) for freq in freqs]) intermedt = time() linearvals = array([sqtlinear(freq) for freq in freqs]) stopt = time() print(f"Adaptive integration took: {intermedt - startt:.1f}") print(f"Linear integration took : {stopt - intermedt:.1f}")
def test_transform_arg_model(): ### Creating a SqE model for transformation sqe_arg = SqE_from_arg(T=20.) ### Instantiate a transformer sqt_arg = SqtTransformer(sqe_arg, corrections=(DetectorEfficiencyCorrectionFactor( sqe_arg, ne=15000, nlam=20), ), ne=15000, nlam=20, lSD=3.43) ### Values for transformation taus = logspace(-6, -1, 11) freqs = MIEZE_DeltaFreq_from_time(taus * 1.0e-9, 3.43, 6.0) ### TRANSFORM!! sqt_argvals = [sqt_arg(freq) for freq in freqs] # For the next step to work, A1 needs to be manually removed # from arg.Sqt calculation. sqt_argmodulevals = arg.Sqt(arg.fqe_I, freqs, -1.0, 0.4, 15000, 20, 3.43, 6.0, 0.12, 0.0, 1.0, 20, 0.00005, 0.1, 350.)
def test_transformer_basics(): ### Creating a SqE model for transformation # We need some lines L1 = LorentzianLine(name="Lorentzian1", domain=(-15.0, 15.0), x0=-1.0, width=0.4, c=0.0, weight=3) # Contruct a SqE model sqe1 = SqE(lines=(L1,), lam=6.0, dlam=0.12, l_SD=3.43, T=20) ### Instantiate a transformer sqt1 = SqtTransformer( sqe1, corrections=(DetectorEfficiencyCorrectionFactor(sqe1, n_e=15000, n_lam=20),), n_e=15000, n_lam=20, l_SD=3.43 ) ### Values for transformation taus = logspace(-6, -1, 11) freqs = MIEZE_DeltaFreq_from_time(taus*1.0e-9, 3.43, 6.0) ### TRANSFORM!! sqt1vals = [sqt1(freq) for freq in freqs] sqt1vals_arg = arg.Sqt( arg.fqe_I, freqs, -1.0, 0.4, 15000, 20, 3.43, 6.0, 0.12, 0.0, 1.0, 20, 0.00005, 0.1, 350. )
def slow_vis_fitting(): ### Creating a SqE model for transformation # We need some lines # L1 = LorentzianLine("Lorentzian1", (-5.0, 5.0), x0=0.0, width=0.4, c=0.0, weight=1) L2 = LorentzianLine(name="Lorentzian2", domain=(-5.0, 5.0), x0=1.5, width=0.4, c=0.0, weight=2) L3 = F_ILine("FI1", (-energy_from_lambda(6.0), 15), x0=0.0, width=0.008, A=350.0, q=0.02, kappa=0.01, c=0.0, weight=1) # Contruct a SqE model sqe1 = SqE((L2, L3), lam=6.0, dlam=0.12, lSD=3.43, T=20) ### Instantiate a transformer # Consider detector efficiency decf = DetectorEfficiencyCorrectionFactor(sqe1) sqt1 = SqtTransformer(sqe1, corrections=(decf, ), ne=10000, nlam=20, lSD=3.43) ### Creating a logger for debugging: import logging # Create and configure logger logging.basicConfig(filename=f"{testdir}/resources/fit.log", level=logging.INFO, filemode="w") logger = logging.getLogger() ### Values for transformation taus = logspace(-6, -1, 101) datataus = array([ 2.0e-6, 6.0e-6, 4.1e-5, 2.5e-4, 5.5e-4, 1.0e-3, 1.32e-3, 1.7e-3, 2.2e-3, 2.63e-3, 2.77e-3, 3.3e-3, 4.27e-3, 5.11e-3, 6.77e-3, 8.96e-3, 2.0e-2 ]) x = MIEZE_DeltaFreq_from_time(datataus * 1.0e-9, 3.43, 6.0) longx = MIEZE_DeltaFreq_from_time(taus * 1.0e-9, 3.43, 6.0) ### TRANSFORM!! y = array([sqt1(freq) for freq in x]) sqt1vals = array([sqt1(freq) for freq in longx]) yerr = 0.03 * random.randn(len(y)) ### FIT! m = FitModelCreator.from_transformer( sqt1, x, abs(y + yerr), yerr, [-1.5, 0.2, 0.0, 3.0, 0.01, 350.0, 0.02, 0.015, 0.0, 1.0], logger=logger) # m.fixed["c_Lorentzian1"] = True m.fixed["c_Lorentzian2"] = True print("fcn for m:\n", m.fcn) m2 = FitModelCreator.from_Minuit( minuitobj=m, # limit_weight_Lorentzian1=(0, None), # limit_width_Lorentzian1=(0, None), limit_weight_Lorentzian2=(0, None), limit_width_Lorentzian2=(0, None), limit_weight_FI1=(0.0, None), limit_kappa_FI1=(0.0, None), # fix_c_Lorentzian1=True, fix_c_Lorentzian2=True, # fix_weight_Lorentzian1=True fix_c_FI1=True, fix_weight_FI1=True, fix_A_FI1=True, fix_q_FI1=True) print("fcn for m2:\n", m2.fcn) # fmin, res = m.migrad(ncall=1000) # print(fmin) # print(res) fmin, res = m2.migrad(ncall=1000) print(fmin) print(res) ### Gather Fit results # dL1res1 = { # "x0" : 0.0, # "width" : res[0].value, # "c" : res[1].value, # "weight" : res[2].value # } # dL2res1 = { # "x0" : res[3].value, # "width" : res[4].value, # "c" : res[5].value, # "weight" : res[6].value # } dL2res1 = { "x0": res[0].value, "width": res[1].value, "c": res[2].value, "weight": res[3].value } dFI1res = { "width": res[4].value, "A": res[5].value, "q": res[6].value, "kappa": res[7].value, "c": res[8].value, "weight": res[9].value } # L1.update_line_params(**dL1res1) L2.update_line_params(**dL2res1) L3.update_line_params(**dFI1res) sqtres1vals = array([sqt1(freq) for freq in longx]) # ### Gather Fit results # dL1res2 = { # "x0" : 0.0, # "width" : res2[0].value, # "c" : res2[1].value, # "weight" : res2[2].value # } # dL2res2 = { # "x0" : res2[3].value, # "width" : res2[4].value, # "c" : res2[5].value, # "weight" : res2[6].value # } # L1.update_line_params(**dL1res2) # L2.update_line_params(**dL2res2) # sqtres2vals = array([sqt1(freq) for freq in longx]) ### Calculate init guess # dL1ig = { # "x0" : 0.0, # "width" : 0.6, # "c" : 0, # "weight" : 1.0 # } # dL2ig = { # "x0" : -1.5, # "width" : 0.2, # "c" : 0.0, # "weight" : 3.0 # } dL2ig = {"x0": -1.5, "width": 0.2, "c": 0.0, "weight": 3.0} dFI1ig = { "x0": 0.0, "width": 0.01, "A": 350, "q": 0.02, "kappa": 0.015, "c": 0.0, "weight": 1.0 } # L1.update_line_params(**dL1ig) L2.update_line_params(**dL2ig) L3.update_line_params(**dFI1ig) sqtigvals = array([sqt1(freq) for freq in longx]) plt.plot(taus, sqt1vals, label="orig. curve", ls="--", color="C0") plt.plot(taus, sqtres1vals, label="fit curve 1", ls="-", color="C1") # plt.plot(taus, sqtres2vals, label="fit curve 2", ls=":", color="C4") plt.plot(taus, sqtigvals, label="init guess", ls="-.", color="C2") plt.errorbar(datataus, abs(y + yerr), yerr, label="data", ls="", marker="o", color="C0") plt.xscale("log") plt.xlabel("$\\tau_{MIEZE}$ [ns]", fontsize=16.) plt.ylabel("S(q,t) [arb. u.]", fontsize=16.) plt.legend() plt.show()
def simple_fit_multi_sqt_curves(transformer, contrastdata, pnames, p0s, cdidx=0, constraints=None, ncalls=150, iomanager=None, export_root=None): """ Finally a function that does what my ipynb does for fitting for one particular model Parameters ---------- transformer : modelmiezelb.transformer.SqtTransformer the theoretical model for the fit contrastdata : iterable contains the modelmiezelb.io.ContrastData objects pnames : iterable contains names of the parameters in the fit p0s : list list of parameter lists. len(p0s) needs to equal len(contrastdata) len(p0s[i]) needs to equal len(pnames) cdidx : int, optional index of the data set within a ContrastData object contstraints : dict, optional contraints for Minuit object ncalls : int, optional number of function calls in Minuit.migrad iomanager : None, modelmiezelb.io.IOManager, optional used for export !!! needs to contain JSONExporter, otherwise filenames do not make sense !!! export_root : str, optional directory where to save the results Needs to be given if iomanager is passed to function Return ------ minuits : list list of Minuit objects after fitting Note ---- This function assumes that MIEZE times are given in nanoseconds (ns)! If not the result is rubbish! """ from time import time, localtime, strftime try: assert len(contrastdata) == len(p0s) assert len(p0s[0]) == len(pnames) except: raise AssertionError("The dimensions of the inputs do not match!\ Check you input for inconsistencies.") minuits = [None] * len(contrastdata) t0 = time() for idx in range(len(contrastdata)): ti = time() tempcd = contrastdata[idx] taus, c, cerr = tempcd.getData(cdidx)[[0, -2, -1]] freqs = MIEZE_DeltaFreq_from_time( taus * 1.0e-9, transformer.params["lSD"], transformer.sqemodel.model_params["lam"]) # Init base Minuit object mbase = FitModelCreator.from_transformer(transformer, freqs, c, cerr, p0s[idx]) # Add constraints default_constraints = { "error_" + n: val * 0.006 for n, val in zip(pnames, p0s[idx]) } if constraints: default_constraints.update(constraints) m = FitModelCreator.from_Minuit(mbase, **default_constraints) fmin, res = m.migrad(ncall=ncalls) minuits[idx] = m print(fmin) print(res) print("Fitting is {}% done.".format( float(idx + 1) / len(contrastdata) * 100)) print("Last iteration took {:.2f} seconds".format(time() - ti)) print("Total seconds elapsed: {:.2f} s".format(time() - t0)) print("The fitting step was finished at {}\n".format( strftime("%H:%M:%S %a %Y/%m/%d", localtime()))) tempcd.fitparams = minuit_to_dict(m) if bool(iomanager) and bool(export_root): export_path = join(export_root, f"{tempcd.get('keys')[cdidx]}") components = [ f"_{k}{str(tempcd.get(k))}" for k in ["foilnum", "arcnum", "description"] if tempcd.get(k) ] export_path += "".join(components) + ".json" iomanager.export((export_path, tempcd)) return minuits