def function_to_sin(fctn: Function): psi = fctn.get_domain() theta = fctn.eval() sinsqrd = np.fromiter(map(lambda x: np.sin(np.deg2rad(x)) ** 2, psi), float) dy = fctn.dy if dy is not None: dy = Function.to_function(sinsqrd, dy.eval()) return Function.to_function(sinsqrd, theta, dy=dy)
def to_function(cls, domain, feval, x_err=None, y_err=None): f = Function.to_function(domain, feval) if x_err is not None: x_err = Function.to_function(domain, x_err) if y_err is not None: y_err = Function.to_function(domain, y_err) return cls(f, x_err, y_err)
def _to_sin_sqr(self, fctn): psi = fctn.get_domain() theta = fctn.eval() sinsqrd = np.fromiter(map(lambda x: np.sin(np.deg2rad(x))**2, psi), float) dy = fctn.dy if not dy.is_null(): dy = Function.to_function(sinsqrd, dy.eval()) return Function.to_function(sinsqrd, theta, dy=dy)
def test_exp(): domain = np.linspace(-5, 5, 100) w_space = np.linspace(-10, 10, 1000) a = 2 f = Function.to_function(domain, lambda x: np.exp(-a * x ** 2)) F_analytical = Function.to_function(w_space, lambda x: np.sqrt(np.pi / a) * np.exp(-x ** 2 / (4 * a))) F = FourierTransform.from_function(w_space, f) assert_equal(F, F_analytical)
def from_file(self): from numpy import loadtxt q, R, dq, dR = loadtxt(self._file).T f = Function.to_function(q, R) df = Function.to_function(q, dR) dx = Function.to_function(q, dq) f.set_dy(df) f.set_dx(dx) return f
def from_file(self): from numpy import loadtxt q, dq, R, dR = loadtxt(self._file, usecols=(0, 1, 2, 3)).T f = Function.to_function(q, R) dx = Function.to_function(q, dq) dy = Function.to_function(q, dR) f.set_dy(dy) f.set_dx(dx) return f
def test_identity_matrix(): x_space = np.linspace(-10, 10, 1000) w_space = np.linspace(-10, 10, 1000) fun = Function(x_space, lambda x: np.exp(-x**2 / 2)) trafo = fourier_matrix(x_space, w_space) f = Function.to_function(w_space, np.dot(trafo, fun(x_space))) trafo = invfourier_matrix(w_space, x_space) fun2 = Function.to_function(x_space, np.dot(trafo, f(w_space))) assert_equal(fun, fun2)
def merge_group(self, group): multi_merge = MultiMerger(MeasurementMerger()) merged = {} for psi, mss in group.items(): merge = multi_merge.merge(mss) merge = ErrorCalculation().manipulate( merge, self._c._settings_controller.get_measurement_context()) theta, dtheta, counts, dcounts = zip(*merge.get_data()) theta = np.array(theta) dx = Function.to_function(theta, dtheta) dy = Function.to_function(theta, dcounts) merged[psi] = Function.to_function(theta, counts, dx=dx, dy=dy) return merged
def remesh(self, interpolation=1, interpolation_kind=None): """ Re-meshes the loaded data onto a common grid by interpolation. Usually, the reflectivity data is not measured at the very same q points. Also the min/max range of the q values might vary. But, to reconstruct the phase, the reflectivity needs to be measured at the same q values. This method achieves this goal. The new grid is the coarsest possible grid. The min/max values are chosen such that every reflectivity measurement contains the min/max values. :param interpolation: integer number. Defines the number of additional interpolations between two q-grid points :param interpolation_kind: interpolation of the function between the point (linear/quadratic/etc..) See scipy.interp1d for possible values :return: None """ # coarsest possible grid qmin = max([ms['Qin'][0] for ms in self._measurements]) qmax = min([ms['Qin'][-1] for ms in self._measurements]) npts = min([len(ms['Qin']) for ms in self._measurements]) new_mesh = np.linspace(qmin, qmax, npts + 1) for measurement in self._measurements: q, R, dR = measurement['Qin'], measurement['Rin'], measurement[ 'dRin'] try: from skipi.function import Function f = Function.to_function( q, R, interpolation=interpolation_kind).remesh( new_mesh).oversample(interpolation) if dR is not None: df = Function.to_function( q, dR, interpolation=interpolation_kind).remesh( new_mesh).oversample(interpolation) dR = df.eval() measurement['Qin'], measurement['Rin'], measurement[ 'dRin'] = f.get_domain(), f.eval(), dR except: # Fallback if skipi is not available q, R = remesh([q, R], qmin, qmax, npts, left=0, right=0) if dR is not None: q, dR = remesh([q, dR], qmin, qmax, npts, left=0, right=0) measurement['Qin'], measurement['Rin'], measurement[ 'dRin'] = q, R, dR
def from_functions(cls, functions: [Function], domain=None, avg_fun=None): if domain is None: domain = functions[0].get_domain() if avg_fun is None: avg_fun = cls.avg return Function.to_function(domain, lambda x: avg_fun([f(x) for f in functions]))
def to_function(cls, frequency_domain, feval, x_domain): dx = Domain.get_dx(frequency_domain) w = numpy.array(x_domain).reshape((len(x_domain), 1)) domain = numpy.array(frequency_domain).reshape( (1, len(frequency_domain))) feval = evaluate(domain, feval) F = trapz(feval * numpy.cos(numpy.dot(w, domain)), dx=dx) return Function.to_function(x_domain, F)
def test_compare_matrix_with_fourier_function(): x_space = np.linspace(-10, 10, 1000) fun = Function(x_space, lambda x: np.exp(-x**2 / 2)) w_space = np.linspace(-10, 10, 1000) f1 = FourierTransform.from_function(w_space, fun) trafo = fourier_matrix(x_space, w_space) f2 = Function.to_function(w_space, np.dot(trafo, fun(x_space))) assert_equal(f1, f2, 1e-14)
def test_compare_InverseFourier_matrix(): x_space = np.linspace(-10, 10, 1000) w_space = np.linspace(-10, 10, 1000) fun = Function(x_space, lambda x: np.exp(-x**2 / 2)) f = FourierTransform.from_function(w_space, fun) trafo = invfourier_matrix(x_space, w_space) fun2 = Function.to_function(w_space, np.dot(trafo, f(x_space))) assert_equal(fun, fun2)
def to_function(cls, frequency_domain, feval, x_domain): # TODO: frequency_domain as Domain? w = numpy.array(x_domain).reshape((len(x_domain), 1)) domain = numpy.array(frequency_domain).reshape( (1, len(frequency_domain))) feval = evaluate(domain, feval) integrand = feval * numpy.exp(1j * numpy.dot(w, domain)) F = 1 / (2 * numpy.pi) * trapz(integrand, dx=Domain.get_dx(frequency_domain)) return Function.to_function(x_domain, F)
def from_function(cls, function: Function): dy = function.dy if dy is None: return function value = numpy.random.normal(function.eval().real, dy.eval().real) if function.is_complex(): value = value + 1j * numpy.random.normal(function.eval().imag, dy.eval().imag) return Function.to_function(function.get_dom(), value)
def test_gauss(): domain = Domain(-1, 1, 10000) #domain = np.linspace(-1, 1, 10000) f = Function.to_function(domain, lambda x: rect(1 / (2 * np.pi) * x)) freq_dom = np.linspace(-20, 20, 1000) F = FourierTransform.from_function(freq_dom, f) fourier_trafo = Function(domain, lambda x: 2 * sinc(x / np.pi)) import pylab pylab.plot(domain.get(), [fourier_trafo(x) for x in domain]) Function.to_function(domain, lambda x: 2*sinc(x/np.pi)).plot() pylab.show() #f.plot() #fourier_trafo.plot() #(f - fourier_trafo).plot(show=True) assert_equal(F, fourier_trafo, TOL=1e-6, do_print=True)
def to_function(cls, domain, feval, frequency_domain): #TODO: frequency_domain as Domain? #domain = Domain.from_domain(domain) #frequency_domain = Domain.from_domain(frequency_domain) #dom = domain.get() #freq_dom = frequency_domain.get() w = numpy.array(frequency_domain).reshape((len(frequency_domain), 1)) feval = evaluate(domain, feval) t_domain = numpy.array(domain).reshape((1, len(domain))) integrand = feval * numpy.exp(-1j * numpy.dot(w, t_domain)) F = trapz(integrand, dx=Domain.get_dx(domain)) return Function.to_function(frequency_domain, F)
def from_functions(cls, functions: [Function], domain=None, std_fun=None): """ Computes the standard deviation (pointwise) using all functions If domain is None, the domain from the first function will be used If std_fun is None, the "complex" standard deviation will be used, see the method cstd. :param functions: A list of functions from which the std should be calculated :param domain: A domain :param std_fun: A function calculating the std :return: new Function """ if domain is None: domain = functions[0].get_domain() if std_fun is None: std_fun = cls.cstd return Function.to_function(domain, lambda x: std_fun([f(x) for f in functions]))
dmax.append((psi, f.argmax())) print(fit.fit_report(show_correl=False)) pylab.show() def function_to_sin(fctn: Function): psi = fctn.get_domain() theta = fctn.eval() sinsqrd = np.fromiter(map(lambda x: np.sin(np.deg2rad(x)) ** 2, psi), float) dy = fctn.dy if dy is not None: dy = Function.to_function(sinsqrd, dy.eval()) return Function.to_function(sinsqrd, theta, dy=dy) def function_to_d(fctn: Function): return fctn.transform(lambda sin, theta: wavelength_k1 / (2*np.sin(np.deg2rad(theta)))) # data = dmax psi, theta = zip(*data) psi = np.array(psi) f = Function.to_function(psi, theta) fpos = function_to_d(function_to_sin(f.vremesh((0, None), dstart=-1))) fneg = function_to_d(function_to_sin(f.vremesh((None, 0)))) pylab.xlabel(xlabel="$\sin^2 \psi") fpos.plot(label='$\psi > 0$') fneg.plot(show=True, label='$\psi < 0$', )
def from_function(cls, fun: Function, **kwargs): domain = fun.get_domain() conv = numpy.convolve(fun(domain), cls.get_kernel(fun, **kwargs), mode='same') return Function.to_function(domain, conv)
def analyze(self): measurements = self._c.measurements # type: uxdconverter.measurement.Measurements psi_measurement_dict = self.merge_group( self.group_measurements_by_psi(measurements)) wavelength_k1 = 0.70931724 wavelength_k2 = 0.71360728 psis = [] thetas = [] for psi, fctn in psi_measurement_dict.items(): if not (psi in self._fitters.keys()): self._fitters[psi] = CorrelatedTwoPeakFit( fctn, wavelength_k1, wavelength_k2) fitter = self._fitters[psi] fit = fitter.get_fit() fitter.plot() print(fit.fit_report(show_correl=False)) if fit.redchi > 1000: continue psis.append(psi) thetas.append(fitter.get_peak_position()) pylab.show() pylab.figure() pylab.xlabel("$sin^2(\psi)$") pylab.ylabel("lattice spacing $[\AA]$") f = Function.to_function(psis, np.array(thetas)) trafo_to_lattice = lambda psi, theta: wavelength_k1 / (2 * np.sin( np.deg2rad(theta))) dy_traf = lambda psi, theta: np.abs( trafo_to_lattice(psi, theta) / np.tan(np.deg2rad(theta))) dy_scale = f.transform(dy_traf) dy_traf = lambda psi, dtheta: dtheta * dy_scale(psi) f = f.transform(trafo_to_lattice, trafo_dy=dy_traf) if f.get_dom().min() < 0: fneg = self._to_sin_sqr(f.vremesh((None, 0))) else: fneg = NullFunction(f.get_dom()) if f.get_dom().max() > 0: fpos = self._to_sin_sqr(f.vremesh((0, None), dstart=-1)) else: fpos = NullFunction(f.get_dom()) fpos.plot(label='$\psi \geq 0$') fneg.plot(label='$\psi < 0$') self.analyze_psi(fpos) self.analyze_psi(fneg) pylab.show() return f
def from_functions(cls, functions: [Function]): return Function.to_function(functions[0].get_dom(), lambda x: numpy.min([f(x) for f in functions]))