def __init__(self, d1, d2, L12=2859.0): """ Calculates the angular resolution for a two slit collimation system. Parameters ---------- d1 : float slit 1 opening d2 : float slit 2 opening L12 : float distance between slits """ alpha = (d1 + d2) / 2.0 / L12 beta = abs(d1 - d2) / 2.0 / L12 self.alpha = alpha self.beta = beta c = (alpha - beta) / 2 / alpha d = (alpha + beta) / 2 / alpha self.rv = stats.trapz(c, d, -alpha, 2 * alpha) self.width = alpha
def correlation_time(self): """ Use the inferred covariance matrix to compute and estimate of the correlation time by approximating the width of correlation for a central knot with it's neighbors. """ ## Select a central knot i_mid = int(len(self.knots) / 2) ## Compute a normalized distribution distribution = np.abs(self.cov[i_mid][1:-1]) distribution = distribution / trapz(distribution, x=self.knots) ## Compute the mean and variance avg = self.knots[i_mid - 1] var = trapz(distribution * (self.knots**2), x=self.knots) - avg**2 return np.sqrt(var)
def __init__( self, model, angle, L12=2859, footprint=60, L2S=120, dtheta=3.3, # angular resolution lo_wavelength=2.8, hi_wavelength=18, dlambda=3.3, rebin=2): self.model = model # turn off resolution smearing self.model.dq = 0 self.bkg = model.bkg.value self.angle = angle # the fractional width of a square wavelength resolution self.dlambda = dlambda / 100. self.rebin = rebin / 100. self.wavelength_bins = calculate_wavelength_bins( lo_wavelength, hi_wavelength, rebin) # nominal Q values bin_centre = 0.5 * (self.wavelength_bins[1:] + self.wavelength_bins[:-1]) self.q = general.q(angle, bin_centre) # keep a tally of the direct and reflected beam self.direct_beam = np.zeros((self.wavelength_bins.size - 1)) self.reflected_beam = np.zeros((self.wavelength_bins.size - 1)) # wavelength generator a = PN('PLP0000711.nx.hdf') q, i, di = a.process(normalise=False, normalise_bins=False, rebin_percent=0, lo_wavelength=lo_wavelength, hi_wavelength=hi_wavelength) q = q.squeeze() i = i.squeeze() self.spectrum_dist = SpectrumDist(q, i) # angular resolution generator, based on a trapezoidal distribution # The slit settings are the optimised set typically used in an # experiment self.dtheta = dtheta / 100. self.footprint = footprint s1, s2 = general.slit_optimiser(footprint, self.dtheta, angle=angle, L2S=L2S, L12=L12, verbose=False) div, alpha, beta = general.div(s1, s2, L12=L12) self.angular_dist = trapz(c=(alpha - beta) / 2. / alpha, d=(alpha + beta) / 2. / alpha, loc=-alpha, scale=2 * alpha)
def time_form_gen(self): earlyt = .2 latet = 13. midt1 = .4 midt2 = 4. # if param already set on object instantiation, leave it alone if 'tf' in self.override: self.FSPS_args['tf'] = self.override['tf'] elif self.tform_key == 'trapz': width = self.time0 - earlyt tformtrap = stats.trapz(loc=earlyt, scale=width, c=(midt1 - earlyt) / width, d=(midt2 - earlyt) / width) tformtrap.random_state = self.RS self.FSPS_args['tf'] = tformtrap.rvs() elif self.tform_key == 'log': self.FSPS_args['tf'] = 10.**self.RS.uniform(low=np.log10(earlyt), high=np.log10(latet)) elif self.tform_key == 'loglinmix': # 25-75 mix between log-uniform and lin-uniform if np.random.rand() < .25: self.FSPS_args['tf'] = 10.**self.RS.uniform( low=np.log10(earlyt), high=np.log10(latet)) else: self.FSPS_args['tf'] = self.RS.uniform(low=earlyt, high=latet) elif self.tform_key == 'norm': # normal distribution tf_min, tf_max = earlyt, latet tf_mean = 5. tf_std = 4. tf_a, tf_b = (tf_min - tf_mean) / tf_std, (tf_max - tf_mean) / tf_std tf_dist = stats.truncnorm(a=tf_a, b=tf_b, loc=tf_mean, scale=tf_std) self.FSPS_args['tf'] = tf_dist.rvs(None, random_state=self.RS) else: self.FSPS_args['tf'] = self.RS.uniform(low=earlyt, high=latet)
def __init__( self, model, angle, L12=2859, footprint=60, L2S=120, dtheta=3.3, lo_wavelength=2.8, hi_wavelength=18, dlambda=3.3, rebin=2, gravity=False, force_gaussian=False, force_uniform_wavelength=False, ): self.model = model self.bkg = model.bkg.value self.angle = angle # dlambda refers to the FWHM of the gaussian approximation to a uniform # distribution. The full width of the uniform distribution is # dlambda/0.68. self.dlambda = dlambda / 100.0 # the rebin percentage refers to the full width of the bins. You have to # multiply this value by 0.68 to get the equivalent contribution to the # resolution function. self.rebin = rebin / 100.0 self.wavelength_bins = calculate_wavelength_bins( lo_wavelength, hi_wavelength, rebin ) bin_centre = 0.5 * ( self.wavelength_bins[1:] + self.wavelength_bins[:-1] ) # angular deviation due to gravity # --> no correction for gravity affecting width of angular resolution elevations = 0 if gravity: speeds = general.wavelength_velocity(bin_centre) # trajectories through slits for different wavelengths trajectories = pm.find_trajectory(L12 / 1000.0, 0, speeds) # elevation at sample elevations = pm.elevation( trajectories, speeds, (L12 + L2S) / 1000.0 ) # nominal Q values self.q = general.q(angle - elevations, bin_centre) # keep a tally of the direct and reflected beam self.direct_beam = np.zeros((self.wavelength_bins.size - 1)) self.reflected_beam = np.zeros((self.wavelength_bins.size - 1)) # beam monitor counts for normalisation self.bmon_direct = 0 self.bmon_reflect = 0 self.gravity = gravity # wavelength generator self.force_uniform_wavelength = force_uniform_wavelength if force_uniform_wavelength: self.spectrum_dist = uniform( loc=lo_wavelength - 1, scale=hi_wavelength - lo_wavelength + 1 ) else: a = PN("PLP0000711.nx.hdf") q, i, di = a.process( normalise=False, normalise_bins=False, rebin_percent=0.5, lo_wavelength=max(0, lo_wavelength - 1), hi_wavelength=hi_wavelength + 1, ) q = q.squeeze() i = i.squeeze() self.spectrum_dist = SpectrumDist(q, i) self.force_gaussian = force_gaussian # angular resolution generator, based on a trapezoidal distribution # The slit settings are the optimised set typically used in an # experiment. dtheta/theta refers to the FWHM of a Gaussian # approximation to a trapezoid. # stores the q vectors contributing towards each datapoint self._res_kernel = {} self._min_samples = 0 self.dtheta = dtheta / 100.0 self.footprint = footprint self.angle = angle self.L2S = L2S self.L12 = L12 s1, s2 = general.slit_optimiser( footprint, self.dtheta, angle=angle, L2S=L2S, L12=L12, verbose=False, ) div, alpha, beta = general.div(s1, s2, L12=L12) self.div, self.s1, self.s2 = s1, s2, div if force_gaussian: self.angular_dist = norm(scale=div / 2.3548) else: self.angular_dist = trapz( c=(alpha - beta) / 2.0 / alpha, d=(alpha + beta) / 2.0 / alpha, loc=-alpha, scale=2 * alpha, )
c, d = 0.2, 0.8 mean, var, skew, kurt = trapz.stats(c, d, moments='mvsk') # Display the probability density function (``pdf``): x = np.linspace(trapz.ppf(0.01, c, d), trapz.ppf(0.99, c, d), 100) ax.plot(x, trapz.pdf(x, c, d), 'r-', lw=5, alpha=0.6, label='trapz pdf') # Alternatively, the distribution object can be called (as a function) # to fix the shape, location and scale parameters. This returns a "frozen" # RV object holding the given parameters fixed. # Freeze the distribution and display the frozen ``pdf``: rv = trapz(c, d) ax.plot(x, rv.pdf(x), 'k-', lw=2, label='frozen pdf') # Check accuracy of ``cdf`` and ``ppf``: vals = trapz.ppf([0.001, 0.5, 0.999], c, d) np.allclose([0.001, 0.5, 0.999], trapz.cdf(vals, c, d)) # True # Generate random numbers: r = trapz.rvs(c, d, size=1000) # And compare the histogram: ax.hist(r, normed=True, histtype='stepfilled', alpha=0.2)