def check(name, chunksize): points = DATASETS[name] ndim = points.shape[1] opts = None nmin = ndim + 2 if name == 'some-points': # since Qz is not allowed, use QJ opts = 'QJ Pp' elif name == 'pathological-1': # include enough points so that we get different x-coordinates nmin = 12 obj = qhull.Voronoi(points[:nmin], incremental=True, qhull_options=opts) for j in xrange(nmin, len(points), chunksize): obj.add_points(points[j:j+chunksize]) obj2 = qhull.Voronoi(points) obj3 = qhull.Voronoi(points[:nmin], incremental=True, qhull_options=opts) obj3.add_points(points[nmin:], restart=True) # -- Check that the incremental mode agrees with upfront mode # The vertices may be in different order or duplicated in # the incremental map for objx in obj, obj3: vertex_map = {-1: -1} for i, v in enumerate(objx.vertices): for j, v2 in enumerate(obj2.vertices): if np.allclose(v, v2): vertex_map[i] = j def remap(x): if hasattr(x, '__len__'): return tuple(set([remap(y) for y in x])) return vertex_map.get(x, x) def simplified(x): items = set(map(sorted_tuple, x)) if () in items: items.remove(()) items = [x for x in items if len(x) > 1] items.sort() return items assert_equal( simplified(remap(objx.regions)), simplified(obj2.regions) ) assert_equal( simplified(remap(objx.ridge_vertices)), simplified(obj2.ridge_vertices) )
def test_incremental(self, name): # Test incremental construction of the triangulation if INCREMENTAL_DATASETS[name][0][0].shape[1] > 3: # too slow (testing of the result --- qhull is still fast) return chunks, opts = INCREMENTAL_DATASETS[name] points = np.concatenate(chunks, axis=0) obj = qhull.Voronoi(chunks[0], incremental=True, qhull_options=opts) for chunk in chunks[1:]: obj.add_points(chunk) obj2 = qhull.Voronoi(points) obj3 = qhull.Voronoi(chunks[0], incremental=True, qhull_options=opts) if len(chunks) > 1: obj3.add_points(np.concatenate(chunks[1:], axis=0), restart=True) # -- Check that the incremental mode agrees with upfront mode assert_equal(len(obj.point_region), len(obj2.point_region)) assert_equal(len(obj.point_region), len(obj3.point_region)) # The vertices may be in different order or duplicated in # the incremental map for objx in obj, obj3: vertex_map = {-1: -1} for i, v in enumerate(objx.vertices): for j, v2 in enumerate(obj2.vertices): if np.allclose(v, v2): vertex_map[i] = j def remap(x): if hasattr(x, '__len__'): return tuple(set([remap(y) for y in x])) try: return vertex_map[x] except KeyError: raise AssertionError( "incremental result has spurious vertex at %r" % (objx.vertices[x], )) def simplified(x): items = set(map(sorted_tuple, x)) if () in items: items.remove(()) items = [x for x in items if len(x) > 1] items.sort() return items assert_equal(simplified(remap(objx.regions)), simplified(obj2.regions)) assert_equal(simplified(remap(objx.ridge_vertices)), simplified(obj2.ridge_vertices))
def _compare_qvoronoi(self, points, output, **kw): """Compare to output from 'qvoronoi o Fv < data' to Voronoi()""" # Parse output output = [list(map(float, x.split())) for x in output.strip().splitlines()] nvertex = int(output[1][0]) vertices = list(map(tuple, output[3:2+nvertex])) # exclude inf nregion = int(output[1][1]) regions = [[int(y)-1 for y in x[1:]] for x in output[2+nvertex:2+nvertex+nregion]] nridge = int(output[2+nvertex+nregion][0]) ridge_points = [[int(y) for y in x[1:3]] for x in output[3+nvertex+nregion:]] ridge_vertices = [[int(y)-1 for y in x[3:]] for x in output[3+nvertex+nregion:]] # Compare results vor = qhull.Voronoi(points, **kw) def sorttuple(x): return tuple(sorted(x)) assert_allclose(vor.vertices, vertices) assert_equal(set(map(tuple, vor.regions)), set(map(tuple, regions))) p1 = list(zip(list(map(sorttuple, ridge_points)), list(map(sorttuple, ridge_vertices)))) p2 = list(zip(list(map(sorttuple, vor.ridge_points.tolist())), list(map(sorttuple, vor.ridge_vertices)))) p1.sort() p2.sort() assert_equal(p1, p2)
def setup_voronoi(): global voro if voro is not None: return setup_padding(10 * dee) while True: voro = qhull.Voronoi(padded_coords) # FIXME check no boundary vertices are touched return
def check(name): points = DATASETS[name] tree = KDTree(points) vor = qhull.Voronoi(points) for p, v in vor.ridge_dict.items(): # consider only finite ridges if not np.all(np.asarray(v) >= 0): continue ridge_midpoint = vor.vertices[v].mean(axis=0) d = 1e-6 * (points[p[0]] - ridge_midpoint) dist, k = tree.query(ridge_midpoint + d, k=1) assert_equal(k, p[0]) dist, k = tree.query(ridge_midpoint - d, k=1) assert_equal(k, p[1])
def test_ridges(self, name): # Check that the ridges computed by Voronoi indeed separate # the regions of nearest neighborhood, by comparing the result # to KDTree. points = DATASETS[name] tree = KDTree(points) vor = qhull.Voronoi(points) for p, v in vor.ridge_dict.items(): # consider only finite ridges if not np.all(np.asarray(v) >= 0): continue ridge_midpoint = vor.vertices[v].mean(axis=0) d = 1e-6 * (points[p[0]] - ridge_midpoint) dist, k = tree.query(ridge_midpoint + d, k=1) assert_equal(k, p[0]) dist, k = tree.query(ridge_midpoint - d, k=1) assert_equal(k, p[1])