def compute_axis_angle(self): x = vonmises.rvs(self.kappa, size=1) y = uniform(0, np.pi) vec_a = self.compute_mean_normal() vec_b, vec_c = self.compute_fracture_normal(vec_a) vec_n = cos(x)*vec_a + sin(x)*(sin(y)*vec_b + cos(y)*vec_c) axis = np.cross(vec_n, vec_a) angle = np.arccos(np.dot(vec_n, vec_a)/2) return axis, angle
def gen_bucketed_vonmesis(): bucketed_data = np.zeros([SAMPLE_SIZE, NUM_BUCKETS + 1]) for kappa in range(1, 6): for i in range(1000): vm_dist = vonmises.rvs(kappa, size=SAMPLE_SIZE) positives = [x + pi for x in vm_dist] bucket_number = [int((x * 180 / pi) // 10) for x in positives] for num in bucket_number: bucketed_data[i][num] += 1 # label the data bucketed_data[i][NUM_BUCKETS] = -2 - kappa np.savetxt('vonmesis_{}.csv'.format(kappa), bucketed_data, delimiter=",")
def computeDirection(self, repellTargets, orientTargets, attractTargets): newWishedDirection = np.zeros(3) # zone of repulsion - highest priority if repellTargets.size > 0: for fish in repellTargets: diff = fish.location - self.location assert np.linalg.norm(diff) > 1e-12, print( diff, "are you satisfying speed*dt<=rRepulsion?") assert np.linalg.norm(diff) < 1e12, print(diff) newWishedDirection -= diff / np.linalg.norm(diff) else: orientDirect = np.zeros(3) attractDirect = np.zeros(3) # zone of orientation if orientTargets.size > 0: for fish in orientTargets: orientDirect += fish.curDirection / np.linalg.norm( fish.curDirection) # zone of attraction if attractTargets.size > 0: for fish in attractTargets: diff = fish.location - self.location attractDirect += diff / np.linalg.norm(diff) newWishedDirection = orientDirect + attractDirect if np.linalg.norm(newWishedDirection) < 1e-12: newWishedDirection = self.curDirection ## stochastic effect, replicates "spherically wrapped Gaussian distribution" # get random unit direction orthogonal to newWishedDirection randVector = self.randUnitDirection() rotVector = np.cross(newWishedDirection, randVector) while np.isclose(np.linalg.norm(rotVector), 0.0): randVector = self.randUnitDirection() rotVector = np.cross(newWishedDirection, randVector) rotVector /= np.linalg.norm(rotVector) # compute random angle from wrapped Gaussian ~ van Mises distribution randAngle = vonmises.rvs(1 / self.sigma**2) # create rotation rotVector *= randAngle r = Rotation.from_rotvec(rotVector) # apply rotation self.wishedDirection = r.apply(newWishedDirection)
def randvonmises(anglegram, i, kappa_scalar=8, random_state=1): """ Sample random value from a von Mises distribution fitted to a histogram """ np.random.seed(random_state) xtorsion = torch.linspace(-np.pi, np.pi, 36) vmexp = torch.sum(xtorsion * anglegram[0, 1:, 0, i]) vmvar = torch.sum(anglegram[0, 1:, 0, i] * (xtorsion - vmexp)**2) vmkappa = 1 / vmvar randvar = vonmises.rvs(kappa=kappa_scalar * vmkappa, loc=vmexp) if randvar < -np.pi: randvar = 2 * np.pi + randvar elif randvar > np.pi: randvar = -2 * np.pi + randvar return randvar
def _make_von_mises_multimodal_sampler(neigh, dirs, vm_distr_kappa=12, approx_len=5000): # Returns a lambda function that is a quick and reliable way to simulate # draws from a Von Mises mixture distribution: # 1.) Chooses a direction by neighborhood-weighted probability # 2.) Makes a random draw from a Von Mises dist centered on the direction, # with a vm_distr_kappa value set such that the net effect, # when doing this a ton of times for a given neighborhood and then # plotting the resulting histogram, gives the visually/heuristically # satisfying approximation of a Von Mises mixture distribution # NOTE: Just visually, heuristically, vm_distr_kappa = 10 seemed # like a perfect middle value (vm_distr_kappa ~3 gives too # wide of a Von Mises variance and just chooses values around # the entire circle regardless of neighborhood # probability, whereas vm_distr_kappa ~20 produces noticeable reductions # in probability of moving to directions between the 8 queen's # neighborhood directions (i.e. doesn't simulate the mixing well enough) # and would generate artefactual movement behavior); 12 also # seemed to really well in generating probability valleys # when tested on neighborhoods that should generate bimodal distributions d = list(dirs.ravel()) n = list(neigh.ravel()) del d[4] del n[4] sum_n = float(sum(n)) if sum_n > 0: n_probs = [i / sum_n for i in n] else: n_probs = [.125] * 8 loc_choices = r.choice(d, approx_len, replace=True, p=n_probs) loc_choices = list(C(loc_choices).items()) approx = np.hstack([ s_vonmises.rvs(vm_distr_kappa, loc=loc, scale=1, size=size) for loc, size in loc_choices ]) return approx
def _make_von_mises_unimodal_sampler(neigh, dirs, vm_distr_kappa=12, approx_len=5000): """Return a list of values approximating a unimodal von Mises distribution pointing in the direction of the maximum-valued cell.""" # list out the directons and their values d = list(dirs.ravel()) n = list(neigh.ravel()) # get rid of focal cell's values del d[4] del n[4] # identify the direction associated with the maximum-valued cell loc = [dirx for idx, dirx in enumerate(d) if n[idx] == max(n)] # get mean of max-valued directions, if there are more than 1 if len(loc) > 1: loc = np.mean(loc) else: loc = loc[0] # make the draws for the approximation vector approx = s_vonmises.rvs(vm_distr_kappa, loc=loc, scale=1, size=approx_len) return approx
def getConnections(neuron): # Sample from circular distribution synapseAngles = vonmises.rvs(kappa=neuron['angleHomogeneity'], loc=neuron['meanAngle'], scale=neuron['angleDistScale'], size=neuron['nSynapses']) # Get synapse distances (sampled from normal distribution) synapseDistances = normal(loc=0.0, scale=neuron['distanceSTD'], size=neuron['nSynapses']) synapseDistances = np.abs( synapseDistances) # Take just positive side of distribution # Generate synapse lines synapses = [] for s in range(neuron['nSynapses']): xEnd = neuron['xPos'] + (np.cos(synapseAngles[s]) * synapseDistances[s]) yEnd = neuron['yPos'] + (np.sin(synapseAngles[s]) * synapseDistances[s]) synapses.append([[neuron['xPos'], xEnd], [neuron['yPos'], yEnd]]) return synapses
def draw_vonmises(kappa, loc, nsamples): # print "kappa, loc: ", kappa, loc # x = 180/pi * vonmises.rvs(kappa, loc=loc, size=nsamples) x = vonmises.rvs(kappa, loc=loc, size=nsamples) return x
# Display the probability density function (``pdf``): x = np.linspace(vonmises.ppf(0.01, kappa), vonmises.ppf(0.99, kappa), 100) ax.plot(x, vonmises.pdf(x, kappa), 'r-', lw=5, alpha=0.6, label='vonmises 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 = vonmises(kappa) ax.plot(x, rv.pdf(x), 'k-', lw=2, label='frozen pdf') # Check accuracy of ``cdf`` and ``ppf``: vals = vonmises.ppf([0.001, 0.5, 0.999], kappa) np.allclose([0.001, 0.5, 0.999], vonmises.cdf(vals, kappa)) # True # Generate random numbers: r = vonmises.rvs(kappa, size=1000) # And compare the histogram: ax.hist(r, normed=True, histtype='stepfilled', alpha=0.2) ax.legend(loc='best', frameon=False) plt.show()
def sim(a, b, plot=False, n=int(1e8)): unwrapped = vonmises.rvs(a, size=n) + vonmises.rvs(b, size=n) unwrapped = unwrapped wrapped = (unwrapped + np.pi) % (2 * np.pi) - np.pi kappa, _, _ = vonmises.fit(wrapped, floc=0, fscale=1) if plot is True: plt.hist(wrapped, normed=True, bins=100) x = np.linspace(-np.pi, np.pi) y = vonmises.pdf(x, kappa) plt.plot(x, y) return kappa # import numpy as np # import pymc3 as pm # import matplotlib.pyplot as plt # import theano.tensor as tt # from scipy.stats import norm, vonmises # from scipy.integrate import quad # # # n = 10000 # mu = 3 # sigma = 3 # # k = np.exp(norm.rvs(mu, sigma, size=n)) # x = vonmises.rvs(kappa=k, size=n) # # with pm.Model(): # # mu = pm.Normal(name="mu", mu=0, sigma=10) # sigma = pm.HalfCauchy(name="sigma", beta=1) # delta = pm.Normal(name="delta", mu=0, sigma=1, shape=n) # kappa = tt.exp(mu + delta * sigma) # IMPORTANT! Use non-centered parameterization # pm.VonMises(name="obs", mu=0, kappa=kappa, observed=x) # trace = pm.sample(10000, tune=5000, chains=2) # pm.traceplot(trace, compact=True, var_names=["mu", "sigma"]) # plt.savefig("tmp.png") # # # hist(x, bins=100, normed=True) # # # # x = np.linspace(-np.pi, np.pi, 100) # # # # def pdf(x, mu, sigma, a): # # g = 1 # # v = vonmises.pdf(x, kappa=mu) # # def f(k, x): # # g = gamma.pdf(k, mu**2 / sigma**2, scale=1. / (mu / sigma**2)) # # v = vonmises.pdf(x, kappa=k) # # return g * v # # return [quad(f, 0, a, _x)[0] for _x in x] # # # # def logpdf(x, mu, sigma, a): # # g = 1 # # v = vonmises.pdf(x, kappa=mu) # # def f(k, x): # # g = gamma.logpdf(k, mu**2 / sigma**2, scale=1. / (mu / sigma**2)) # # v = vonmises.logpdf(x, kappa=k) # # return g * v # # return [quad(f, 0, a, _x)[0] for _x in x] # # # # [plot(x, pdf(x, mu, sigma, a)) for a in [500]] # # # # # # plot(x, np.log(pdf(x, mu, sigma))) # # # # # # # # from scipy.integrate import quad # # import theano # # import theano.tensor as tt # # import numpy as np # # import pymc3 as pm # # # # # # class Integrate(theano.Op): # # def __init__(self, expr, var, *extra_vars): # # super().__init__() # # self._expr = expr # # self._var = var # # self._extra_vars = extra_vars # # self._func = theano.function( # # [var] + list(extra_vars), # # self._expr, # # on_unused_input='ignore') # # # # def make_node(self, start, stop, *extra_vars): # # self._extra_vars_node = extra_vars # # assert len(self._extra_vars) == len(extra_vars) # # self._start = start # # self._stop = stop # # vars = [start, stop] + list(extra_vars) # # # vars = list(extra_vars) # # return theano.Apply(self, vars, [tt.dscalar().type()]) # # # # def perform(self, node, inputs, out): # # start, stop, *args = inputs # # val = quad(self._func, start, stop, args=tuple(args))[0] # # out[0][0] = np.array(val) # # # # def grad(self, inputs, grads): # # start, stop, *args = inputs # # out, = grads # # replace = dict(zip(self._extra_vars, args)) # # # # replace_ = replace.copy() # # replace_[self._var] = start # # dstart = out * theano.clone(-self._expr, replace=replace_) # # # # replace_ = replace.copy() # # replace_[self._var] = stop # # dstop = out * theano.clone(self._expr, replace=replace_) # # # # grads = tt.grad(self._expr, self._extra_vars) # # dargs = [] # # for grad in grads: # # integrate = Integrate(grad, self._var, *self._extra_vars) # # darg = out * integrate(start, stop, *args) # # dargs.append(darg) # # # # return [dstart, dstop] + dargs # # # # # # y_obs = 8.3 # # # # start = theano.shared(1.) # # stop = theano.shared(2.) # # with pm.Model() as basic_model: # # a = pm.Uniform('a', 1.5, 3.5) # # b = pm.Uniform('b', 4., 6.) # # # # # Define the function to integrate in plain theano # # t = tt.dscalar('t') # # t.tag.test_value = np.zeros(()) # # a_ = tt.dscalar('a_') # # a_.tag.test_value = np.ones(())*2. # # b_ = tt.dscalar('b_') # # b_.tag.test_value = np.ones(())*5. # # func = t**a_ + b_ # # integrate = Integrate(func, t, a_, b_) # # # # # Now we plug in the values from the model. # # # The `a_` and `b_` from above corresponds to the `a` and `b` here. # # mu = integrate(start, stop, a, b) # # y = pm.Normal('y', mu=mu, sd=0.4, observed=y_obs) # # trace = pm.sample(1500, tune=500, cores=2, chains=2)
def draw_vonmises(kappa, loc, nsamples): # print "kappa, loc: ", kappa, loc # x = 180/pi * vonmises.rvs(kappa, loc=loc, size=nsamples) x = vonmises.rvs(kappa, loc=loc, size=nsamples) # fvm.write("%f\n" % x[0]) return x
ncounts = 1000 xx = [] yy = [] zz = [] # Loop through all photons for i in range(ncounts): # Select a wavelength wavelength = normalvariate(wavelength_mean, wavelength_sigma) if wavelength <= 0: continue # Select a divergence divangle = vonmises.rvs(divangle_kappa), uniform(0, 2 * pi) # Select a mosaic angular spread angle mosangle = vonmises.rvs(mosangle_kappa), uniform(0, 2 * pi) # Select a mosaic size point mossize_xyz = multivariate_normal( [0.0, 0.0, 0.0], [ [mossize_sigma, 0.0, 0.0], [0.0, mossize_sigma, 0.0], [0.0, 0.0, mossize_sigma], ], ) # Select a mosaic spread in unit cell sizes points