def test_bounding_ball_optimality(): # Check that the bounding ball are optimal for n in range(2, 10): for count in range(n + 2, n + 30): # Generate a support sphere from n+1 points S_support = numpy.random.randn(n + 1, n) C_support, r2_support = miniball.get_bounding_ball(S_support) # Generate points inside the support sphere S = numpy.random.randn(count - S_support.shape[0], n) S /= numpy.sqrt(numpy.sum(S ** 2, axis=1))[:, None] S *= (0.9 * numpy.sqrt(r2_support)) * numpy.random.rand( count - S_support.shape[0], 1 ) S = S + C_support # Get the bounding sphere C, r2 = miniball.get_bounding_ball( numpy.concatenate([S, S_support], axis=0) ) # Check that the bounding sphere and the support sphere are equivalent # up to machine precision. assert numpy.allclose(r2, r2_support) assert numpy.allclose(C, C_support)
def test_integer_coordinates(): # Check that integer coordinates are properly handled for n in range(1, 10): S_int = numpy.random.randint(-1000, 1500, (100, 2)) C_int, r2_int = miniball.get_bounding_ball(S_int) S = S_int.astype(float) C, r2 = miniball.get_bounding_ball(S) assert numpy.allclose(C, C_int) assert numpy.allclose(r2, r2_int)
def test_repeatability(): # Check that we can have repeatable results when providing the RNG epsilon = 1e-5 rng_seed = 42 S = numpy.random.randn(100, 2) C_a, r2_a = miniball.get_bounding_ball( S, rng=numpy.random.default_rng(seed=rng_seed) ) C_b, r2_b = miniball.get_bounding_ball( S, rng=numpy.random.default_rng(seed=rng_seed) ) assert (C_a == C_b).all() assert (r2_a == r2_b).all()
def bounding_circle(self): """tuple[float, float]: Get the center and radius of the bounding circle.""" # noqa: E501 if not MINIBALL: raise ImportError("The miniball module must be installed. It can " "be installed as an extra with coxeter (e.g. " "with pip install coxeter[bounding_sphere], or " "directly from PyPI using pip install miniball.") # The algorithm in miniball involves solving a linear system and # can therefore occasionally be somewhat unstable. Applying a # random rotation will usually fix the issue. max_attempts = 10 attempt = 0 current_rotation = [1, 0, 0, 0] vertices = self.vertices while attempt < max_attempts: attempt += 1 try: center, r2 = miniball.get_bounding_ball(vertices) break except np.linalg.LinAlgError: current_rotation = rowan.random.rand(1) vertices = rowan.rotate(current_rotation, vertices) if attempt == max_attempts: raise RuntimeError("Unable to solve for a bounding sphere.") # The center must be rotated back to undo any rotation. center = rowan.rotate(rowan.conjugate(current_rotation), center) return Circle(np.sqrt(r2), center)
def minimal_bounding_sphere(self): """:class:`~.Sphere`: Get the polyhedron's bounding sphere.""" if not MINIBALL: raise ImportError( "The miniball module must be installed. It can " "be installed as an extra with coxeter (e.g. " 'with "pip install coxeter[bounding_sphere]") or ' 'directly from PyPI using "pip install miniball".' ) # The algorithm in miniball involves solving a linear system and # can therefore occasionally be somewhat unstable. Applying a # random rotation will usually fix the issue. max_attempts = 10 attempt = 0 current_rotation = [1, 0, 0, 0] vertices = self.vertices while attempt < max_attempts: attempt += 1 try: center, r2 = miniball.get_bounding_ball(vertices) break except np.linalg.LinAlgError: current_rotation = rowan.random.rand(1) vertices = rowan.rotate(current_rotation, vertices) else: raise RuntimeError("Unable to solve for a bounding sphere.") # The center must be rotated back to undo any rotation. center = rowan.rotate(rowan.conjugate(current_rotation), center) return Sphere(np.sqrt(r2), center)
def learn(self, k, w_init): model_store = [] core_store = [] for _ in range(k): core_num = self.n // k rng = np.random.default_rng() X = rng.normal(loc=self.X_mean, size=(self.n, self.d), scale=self.X_var) tmp = noise2.Noise(dim=self.d, mean=0, sigma=self.E_var, n=self.n) E = getattr(tmp, self.noise)() Y = np.dot(self.w_star, X.T) + E data = [X, Y.T] core = algo_sgd.SGD(w_init=w_init, a=self.lr, t_max=core_num - 1, data=data) for _ in core: core.update(self.loss_type) core_store.append(core.wstore) model_store.append(core.w) w_dc, _ = miniball.get_bounding_ball(np.array(model_store).reshape( (-1, self.d)), epsilon=1e-7) w_dc = w_dc.reshape(1, -1) excess_risk = self.loss_type.excess_risk_normal(X_mean=self.X_mean, X_var=self.X_var, w_star=self.w_star, w=w_dc) return w_dc, excess_risk, core_store
def writeBinaryToString(): fname = "gltf/box.gltf" gltf = GLTF2().load(fname) # get the first mesh in the current scene (in this example there is only one scene and one mesh) mesh = gltf.meshes[gltf.scenes[gltf.scene].nodes[0]] # get the vertices for each primitive in the mesh (in this example there is only one) for primitive in mesh.primitives: # get the binary data for this mesh primitive from the buffer accessor = gltf.accessors[primitive.attributes.POSITION] bufferView = gltf.bufferViews[accessor.bufferView] buffer = gltf.buffers[bufferView.buffer] data = gltf.decode_data_uri(buffer.uri) # pull each vertex from the binary buffer and convert it into a tuple of python floats vertices = [] for i in range(accessor.count): index = bufferView.byteOffset + accessor.byteOffset + i * 12 # the location in the buffer of this vertex d = data[index:index + 12] # the vertex data v = struct.unpack("<fff", d) # convert from base64 to three floats vertices.append(v) print(i, v) # convert a numpy array for some manipulation S = numpy.array(vertices) # use a third party library to perform Ritter's algorithm for finding smallest bounding sphere C, radius_squared = miniball.get_bounding_ball(S) # output the results print( f"center of bounding sphere: {C}\nradius squared of bounding sphere: {radius_squared}" )
def find_bounding_circle(systems): S = np.array(systems) # The algorithm implemented is Welzl’s algorithm. It is a pure Python implementation, # it is not a binding of the popular C++ package Bernd Gaertner’s miniball. # The algorithm, although often presented in its recursive form, is here implemented in an iterative fashion. # Python have an hard-coded recursion limit, therefore a recursive implementation of Welzl’s # algorithm would have an artificially limited number of point it could process. C, r2 = miniball.get_bounding_ball(S) return C
def find_miniball(self): """Finds the "miniball," the smallest circle that can enclose all of the triangles vertices Returns ------- nothing, values are stored in "private" attributes """ c, r2 = miniball.get_bounding_ball(self.vertices_array) self._mini_center = Coordinate(c[1], c[0]) self._mini_radius = sqrt(r2)
def test_bounding_ball_contains_point_set(): # Check that the computed bounding ball contains all the input points for n in range(1, 10): for count in range(2, n + 10): # Generate points S = numpy.random.randn(count, n) # Get the bounding sphere C, r2 = miniball.get_bounding_ball(S) # Check that all points are inside the bounding sphere up to machine precision assert numpy.all(numpy.sum((S - C) ** 2, axis=1) - r2 < 1e-12)
def transition(self, k, w_init): _, _, core_store = self.learn(k=k, w_init=w_init) w_transition = [] loss_transition = [] core_store = np.array(core_store) tmp = core_store.shape core_num, update_num, _, w_dim = tmp core_store = core_store.reshape(core_num, update_num, w_dim) core_store = core_store.transpose(1, 0, 2) for i in range(update_num): w, _ = miniball.get_bounding_ball(core_store[i, :, :]) w_transition.append(w) loss_transition.append( self.loss_type.excess_risk_normal(X_mean=self.X_mean, X_var=self.X_var, w_star=self.w_star, w=w.reshape(1, w_dim))) return w_transition, loss_transition
pts_in_range = [] for [x, y, z] in tqdm(points): inRange = True for system in results: dist = math.sqrt((results[system]['coords']['x'] - x)**2 + (results[system]['coords']['y'] - y)**2 + (results[system]['coords']['z'] - z)**2) if ((dist > systems[system]['max']) or (dist < systems[system]['min'])): inRange = False if inRange: pts_in_range.append([x, y, z]) #Calculating valid points bounding sphere pts_in_range = np.array(pts_in_range) C, r2 = miniball.get_bounding_ball(pts_in_range) #Get known systems in sphere print('Fetching targets') targets = EDSM_lib.GetSphereSystemsXYZ(C[0], C[1], C[2], math.sqrt(r2), 0, 1, 1, 1, 1, 1) targets = sorted(targets, key=lambda i: i['distance'], reverse=False) print('Target center', C) print('Target radius', math.sqrt(r2)) print('Known targets nearby:') print('{:30} {:3}'.format('Name', 'Distance')) for target in targets: print('{:30} {:3}'.format(target['name'], target['distance']))
def cluster(img, eps, min_samples, backend="dbscan", nthreads=2, fit_kind="circle"): """ Cluster group of pixels. Parameters: ---------- img : np.ndarray Input image. Must be binary. eps : float Maximum distance allowed to form a cluster. min_samples : int Minimum number of samples to form a cluster. backend : str Which backend to use for clustering. Default is DBSCAN. fit_kind : str What type of geometry to fir to the clusters. Default is circle. Returns: ------- df : pd.DataFrame A dataframe with the clustering results. """ ipx, jpx = np.where(img) # gets where img == 1 X = np.vstack([ipx, jpx]).T if len(X) > min_samples: if backend.lower() == "optics": db = OPTICS(cluster_method="dbscan", metric="euclidean", eps=eps, max_eps=eps, min_samples=min_samples, min_cluster_size=min_samples, n_jobs=nthreads, algorithm="ball_tree").fit(X) labels = db.labels_ elif backend.lower() == "hdbscan": db = hdbscan.HDBSCAN(min_cluster_size=int(min_samples), metric="euclidean", allow_single_cluster=True, core_dist_n_jobs=nthreads) labels = db.fit_predict(X) elif backend.lower() == "dbscan": db = DBSCAN(eps=eps, metric="euclidean", min_samples=min_samples, n_jobs=nthreads, algorithm="ball_tree").fit(X) labels = db.labels_ else: raise ValueError("Use either DBSCAN or OPTICS.") # to dataframe df = pd.DataFrame(X, columns=["j", "i"]) df["cluster"] = labels df = df[df["cluster"] >= 0] # get centers and radii cluster = [] i_center = [] j_center = [] n_pixels = [] R1 = [] R2 = [] theta = [] for cl, gdf in df.groupby("cluster"): # fit a circle if fit_kind == "circle": c, r2 = miniball.get_bounding_ball( gdf[["i", "j"]].values.astype(float)) xc, yc = c r1 = np.sqrt(r2) r2 = r1 # these are for ellipses only t = 0 # these are for ellipses only elif fit_kind == "ellipse": try: # compute the minmun bounding ellipse A, c = mvee(gdf[["i", "j"]].values.astype(float)) # centroid xc, yc = c # radius, angle and eccentricity r1, r2, t, _ = get_ellipse_parameters(A) except Exception: # fall back to circle c, r2 = miniball.get_bounding_ball( gdf[["i", "j"]].values.astype(float)) xc, yc = c r1 = np.sqrt(r2) r2 = r1 # these are for ellipses only t = 0 # these are for ellipses only else: raise ValueError("Can only fit data to circles or ellipses.") # append to output i_center.append(xc) j_center.append(yc) cluster.append(cl) n_pixels.append(len(gdf)) R1.append(r1) R2.append(r2) theta.append(t) # to dataframe x = np.vstack([i_center, j_center, n_pixels, R1, R2, theta, cluster]).T columns = ["ic", "jc", "pixels", "ir", "jr", "theta_ij", "cluster"] df = pd.DataFrame(x, columns=columns) return df else: return pd.DataFrame()
def smallball(X): tmp = np.array(X) return miniball.get_bounding_ball(tmp)[0]
import numpy as np import time import miniball S = np.loadtxt('dataset.txt') #S = np.random.randn(100,10) tic = time.time() C, r2 = miniball.get_bounding_ball(S) #print (f'center is = {C}') print(f'radius squared is = {r2}') print(f'Total time = {time.time() - tic} sec') np.savetxt('rad.txt', (C, r2))