def get_wigner_seitz_cell(self): """ Returns the Wigner-Seitz cell for the given lattice. Returns: A list of list of coordinates. Each element in the list is a "facet" of the boundary of the Wigner Seitz cell. For instance, a list of four coordinates will represent a square facet. """ from pyhull.voronoi import VoronoiTess vec1 = self.matrix[0] vec2 = self.matrix[1] vec3 = self.matrix[2] list_k_points = [] for i, j, k in itertools.product([-1, 0, 1], [-1, 0, 1], [-1, 0, 1]): list_k_points.append(i * vec1 + j * vec2 + k * vec3) tess = VoronoiTess(list_k_points) to_return = [] for r in tess.ridges: if r[0] == 13 or r[1] == 13: to_return.append([tess.vertices[i] for i in tess.ridges[r]]) return to_return
def _set_voronoi_bond_orders(self): ''' approximate bond order, from purely geometric voronoi solid angles' returns def bond_order(cd): ''' p = self.positions bond_orders = [] o_index = p.shape[1] / 2 n_images = p.shape[1] for i in range(p.shape[2]): #[atomj * image, axis] vt = VoronoiTess(p[:, :, i].reshape((-1, 3))) bo = np.zeros([p.shape[0] * p.shape[1]] * 2) vts = np.array(vt.vertices) for (k1, k2), v in vt.ridges.items(): if (k1 % n_images != o_index) and (k2 % n_images != o_index): continue if -10.101 in vts[v]: continue val = solid_angle(vt.points[k1], vts[v]) bo[k1, k2] = val bo[k2, k1] = val nshape = (p.shape[0], p.shape[0], p.shape[1], 1) bond_orders.append(bo[o_index::n_images].reshape(nshape)) self._voronoi_bond_orders = np.concatenate(bond_orders, -1)
def setup_voronoi_list(self, indices, voronoi_cutoff): """ Set up of the voronoi list of neighbours by calling qhull :param indices: indices of the sites for which the Voronoi is needed :param voronoi_cutoff: Voronoi cutoff for the search of neighbours :raise RuntimeError: If an infinite vertex is found in the voronoi construction """ self.voronoi_list = [None] * len(self.structure) logging.info('Getting all neighbors in structure') struct_neighbors = self.structure.get_all_neighbors(voronoi_cutoff, include_index=True) t1 = time.clock() logging.info('Setting up Voronoi list :') for jj, isite in enumerate(indices): logging.info( ' - Voronoi analysis for site #{:d} ({:d}/{:d})'.format( isite, jj + 1, len(indices))) site = self.structure[isite] neighbors1 = [(site, 0.0, isite)] neighbors1.extend(struct_neighbors[isite]) distances = [i[1] for i in sorted(neighbors1, key=lambda s: s[1])] neighbors = [i[0] for i in sorted(neighbors1, key=lambda s: s[1])] qvoronoi_input = [s.coords for s in neighbors] voro = VoronoiTess(qvoronoi_input) all_vertices = voro.vertices results = [] maxangle = 0.0 mindist = 10000.0 for nn, vind in list(voro.ridges.items()): if 0 in nn: if 0 in vind: raise RuntimeError("This structure is pathological," " infinite vertex in the voronoi " "construction") facets = [all_vertices[i] for i in vind] try: sa = solid_angle(site.coords, facets) except ValueError: sa = my_solid_angle(site.coords, facets) maxangle = max([sa, maxangle]) mindist = min([mindist, distances[nn[1]]]) for iii, sss in enumerate(self.structure): if neighbors[nn[1]].is_periodic_image(sss): myindex = iii break results.append((neighbors[nn[1]], { 'angle': sa, 'distance': distances[nn[1]], 'index': myindex })) for (nn, dd) in results: dd['weighted_angle'] = dd['angle'] / maxangle dd['weighted_distance'] = dd['distance'] / mindist self.voronoi_list[isite] = results t2 = time.clock() logging.info('Voronoi list set up in {:.2f} seconds'.format(t2 - t1))
def voroArea(topAtoms, qry, maxX, maxY): topCRDs = topAtoms.coordinates() #convert 3D to 2D: extractig X and Y axis topCRDs = selCoord(topCRDs, [0, 1]) topPoints = getNumPoints(topAtoms, qry) uq_resNames = topPoints[0] # Residues names in the given system uq_numAtoms = topPoints[1] # the number of selected atoms corresponding to residue names # calculating voronoi tessellation voro = VoronoiTess(topCRDs) voro_vtex = voro.vertices voro_regn = voro.regions # calculating area per lipids resIDs = topAtoms.resids() # obtaining residue ids resNames = topAtoms.resnames() # initializing array areaLipids = [0] * (len(resIDs) + 1) # each array will be used for individual lipid area and last one will be the average area res_cnt = 0 # residue count num_atoms = 0 # number of atoms corresponding to the current residue name crd_idx = 0 # coordinate index for res_name in resNames: # find corresponding residue num_atoms = uq_numAtoms[uq_resNames.index(res_name)] #calculating the area corresponding to the point atom_cnt = 0 myarea = 0.0 for dummy in range(num_atoms): print crd_idx my_region = getPos(voro_regn[crd_idx]) liparea = crdArea(my_region, voro_vtex, maxX, maxY) print liparea crd_idx = crd_idx + 1 myarea = myarea + liparea areaLipids[res_cnt] = myarea res_cnt = res_cnt + 1 areaLipids[len(areaLipids) - 1] = sum(areaLipids) / res_cnt print crd_idx print len(topCRDs) return areaLipids
def get_wigner_seitz(self): if HAS_PYHULL: from pyhull.voronoi import VoronoiTess points = [] for i, j, k in itertools.product((-1, 0, 1), repeat=3): points.append(i * self.cell[0] + j * self.cell[1] + k * self.cell[2]) tess = VoronoiTess(points) ret = [] for r in tess.ridges: if r[0] == 13 or r[1] == 13: ret.append([tess.vertices[i] for i in tess.ridges[r]]) return ret else: raise NotImplementedError
def setUp(self): data = [[0, 0], [-0.5, -0.5], [-0.5, 0.5], [0.5, -0.5], [0.5, 0.5]] self.voro = VoronoiTess(data) sphere_data = [ [0.3927286959385721, 0.3027233106882571, -0.0642087887467873], [-0.3040289937812381, 0.08411211324060132, -0.3879323695524365], [-0.4167147320140305, -0.1124203247935928, 0.252409395022804], [-0.09784613055257477, 0.3994051836806832, 0.2844321254445218], [0.0167085276338464, 0.4969839143091518, 0.05222847903455247], [-0.3010383814570601, 0.3973744439739354, 0.03833332970300512], [0.321916886905792, -0.3514017778986294, -0.1512822144687402], [-0.02357104947939958, 0.4654006301246191, -0.1812364728912125], [0.3199720537828011, -0.3299443654301472, -0.1968618818332127], [-0.4630278928730662, -0.1886147011806086, 0.005446551209538857] ] self.spvoro = VoronoiTess(sphere_data) #Make sure higher dim works. points = np.random.randn(10, 5) self.hdvoro = VoronoiTess(points) #Check that bad points raises an error. bad_points = [[0, 0], [0, 1, 0], [0, 0]] self.assertRaises(ValueError, VoronoiTess, bad_points)
def connectivity_array(self): """ Provides connectivity array. Returns: connectivity: An array of shape [atomi, atomj, imagej]. atomi is the index of the atom in the input structure. Since the second atom can be outside of the unit cell, it must be described by both an atom index and an image index. Array data is the solid angle of polygon between atomi and imagej of atomj """ #shape = [site, axis] cart_coords = np.array(self.s.cart_coords) #shape = [site, image, axis] all_sites = cart_coords[:, None, :] + self.cart_offsets[None, :, :] vt = VoronoiTess(all_sites.reshape((-1, 3))) n_images = all_sites.shape[1] cs = (len(self.s), len(self.s), len(self.cart_offsets)) connectivity = np.zeros(cs) vts = np.array(vt.vertices) for (ki, kj), v in vt.ridges.items(): atomi = ki // n_images atomj = kj // n_images imagei = ki % n_images imagej = kj % n_images if imagei != n_images // 2 and imagej != n_images // 2: continue if imagei == n_images // 2: #atomi is in original cell val = solid_angle(vt.points[ki], vts[v]) connectivity[atomi, atomj, imagej] = val if imagej == n_images // 2: #atomj is in original cell val = solid_angle(vt.points[kj], vts[v]) connectivity[atomj, atomi, imagei] = val if -10.101 in vts[v]: warn('Found connectivity with infinite vertex. ' 'Cutoff is too low, and results may be ' 'incorrect') return connectivity
def generate_tesselation(self): """Generate and return the tesselation as prescribed by the arguments of the __init__() function Returns ------- random_mesh : Mesh type a mesh object with based on random voronoi seeds of the requested size, and where the requested number of Lloyd relaxation steps has been applied """ # First, we generate an initial tesselation. This is where the random seeds are made and the internal # mesh variable are first written self.generate_initial_tesselation() # if the user does not request relaxation steps, just return this mesh if (self.number_of_relaxation_steps == 0): # we need to crop the mesh before we return it, i.e. cut of the regions and cells that we added # to hide boundary effects return self.crop_and_return_mesh() else: # if relaxation steps are required we perform them for iteration in range(self.number_of_relaxation_steps): # get the centroids of the existing mesh centroid_positions = [] for element in self.mesh.elements: centroid_positions.append(element.calculate_centroid()) # add our padding centroids, i.e. two rows of regularly spaced centroids # on the outside of the entire region of interest (which includes extra space and cells) all_centroid_positions = np.vstack( (np.array(centroid_positions), self.padding_centroid_positions)) # We generate a Voronoi tesselation of that self.voronoi_diagram = VoronoiTess(all_centroid_positions) # now we clean up that voronoi tesselation and set the mesh in the generator self.remove_padding_cells_from_voronoi_diagram_and_create_mesh( ) # after we went through the iterations we can crop and return the mesh return self.crop_and_return_mesh()
def get_voronoi_polyhedra(self, n): """ Gives a weighted polyhedra around a site. This uses the voronoi construction with solid angle weights. See ref: A Proposed Rigorous Definition of Coordination Number, M. O'Keeffe, Acta Cryst. (1979). A35, 772-775 Args: n: site index Returns: A dictionary of sites sharing a common Voronoi facet with the site n and their solid angle weights """ localtarget = self._target center = self._structure[n] neighbors = self._structure.get_sites_in_sphere( center.coords, VoronoiCoordFinder.default_cutoff) neighbors = [i[0] for i in sorted(neighbors, key=lambda s: s[1])] qvoronoi_input = [s.coords for s in neighbors] voro = VoronoiTess(qvoronoi_input) all_vertices = voro.vertices results = {} for nn, vind in voro.ridges.items(): if 0 in nn: if 0 in vind: raise RuntimeError("This structure is pathological," " infinite vertex in the voronoi " "construction") facets = [all_vertices[i] for i in vind] results[neighbors[nn[1]]] = solid_angle(center.coords, facets) maxangle = max(results.values()) resultweighted = {} for nn, angle in results.items(): if nn.specie in localtarget: resultweighted[nn] = angle / maxangle return resultweighted
def generate_initial_tesselation(self): """Generate the initial tesselation. In this method we distribute nx_with_dummies*ny_with_dummies points randomly in a box of dimension [nx_with_dummies, ny_with_dummies]. We then add the padding centroids on the outside of the box to `cut of' infinity. Finally, we take the voronoi tesselation of all these centroids, and remove the voronoi cells originating from the padding centroids from this tesselation. This is designed such that the average area of the remaining cells should be one. """ total_number_of_random_points_to_create = np.prod( self.nx_with_dummies * self.ny_with_dummies) # We make a mesh of cell centroids. # First we get an array with random entries between 0 and 1 in x and y directions of correct length centroid_positions = np.random.rand( total_number_of_random_points_to_create, 2) # Then we blow this array up to the correct dimensions in x and y centroid_positions[:, 0] *= self.nx_with_dummies centroid_positions[:, 1] *= self.ny_with_dummies # and we shift the mesh such that the bottom and left added space is negative centroid_positions[:, 0] -= 3.5 centroid_positions[:, 1] -= 3.5 # the region with the centroids now spreads from -3.5 to (self.[nx/ny] + 4.5) so that we can add padding # cells at integer coordinates, i.e -4 and self.[nx/ny] + 5 # Now we add some padding cells on the outside. centroid_positions = np.vstack( (centroid_positions, self.padding_centroid_positions)) # We generate a Voronoi tesselation of that self.voronoi_diagram = VoronoiTess(centroid_positions) # now we clean up this voronoi tesselation and set the mesh of the generator # cleaning up means we remove the voronoi cells originating from the padding seeds self.remove_padding_cells_from_voronoi_diagram_and_create_mesh()
from pyhull.convex_hull import ConvexHull from pyhull.voronoi import VoronoiTess #pts = [[-0.5, -0.5], [-0.5, 0.5], [0.5, -0.5], [0.5, 0.5], [0,0]] pts = [[44.968046,-94.420307],[44.33328,-89.132008],[33.755787,-116.359998],[33.844843,-116.54911],[44.92057,-93.44786], [44.240309,-91.493619], [44.968041,-94.419696], [44.333304,-89.132027], [33.755783,-116.360066], [33.844847,-116.549069], [44.920474,-93.447851], [44.240304,-91.493768]] pts_reversed = [] for pt in pts: pts_reversed.append([pt[1], pt[0]]) print pts_reversed hull = VoronoiTess (pts) print hull.vertices
from mpl_toolkits.mplot3d import axes3d, Axes3D import numpy as np import scipy as sp import scipy.misc import math import matplotlib.pyplot as plt from pyhull.voronoi import VoronoiTess V = np.array([[0, 0, 0], [0, 1, 0], [1, 1, 1], [2, 1, 2], [3, 2, 1]]) plt.gca(projection='3d') plt.plot(V[:, 0], V[:, 1], V[:, 2], 'o') vor = VoronoiTess(V) vorVer = np.array(vor.vertices) print vorVer plt.plot(vorVer[:, 0], vorVer[:, 1], vorVer[:, 2]) plt.show()
def check_road_segment(r_id, road, building_data, bld_geoms, bld_ids, method, idx): """ This function runs for every road segment the main logic. It creates a buffer, finds the buildings in the buffer, constructs abounding box, creates the voronoi, finds relationshipds between road segments and buildings, and the calls the classification. """ road_to_building = {} classification = {} points_classified = {} # Create equidistant points along the road segment. road_coords = list(road.coords) eq_pts_road = discretise_road(road_coords) # Create buffer around the road (60m) and return all of its coordinates. # Discretise the buffer based on these coordinates for bounding the Voronoi. road_simple = road.simplify(5, preserve_topology=True) # Get the buffers for the roads and road sub-segments in the case the # road is too complex. sub_buffers = get_buffer_parts(r_id, road_simple) for new_id in sub_buffers: points_classified[new_id] = {} points_classified[new_id]['geom'] = {} points_classified[new_id]['class'] = {} road_part = sub_buffers[new_id]['new_road'] classification[new_id] = {'geom': road_part} road_to_building[new_id] = {} # Find the buildings in the 60m buffer. blds_left_buffer = get_buildings_in_buffer(sub_buffers[new_id]['left'], bld_geoms, bld_ids, idx) blds_right_buffer = get_buildings_in_buffer( sub_buffers[new_id]['right'], bld_geoms, bld_ids, idx) # No buildings on either side of the road, go to the next road segment. if not blds_left_buffer and not blds_right_buffer: classification[new_id]['class'] = 4 continue # Discretise the buildings for the voronoi. eq_pts_blds_left, eq_pts_blds_left_flat = discretise_buildings( blds_left_buffer) eq_pts_blds_right, eq_pts_blds_right_flat = discretise_buildings( blds_right_buffer) # Create voronoi diagram out of the building, road and bounding box points. bbox = construct_bbox(eq_pts_road + eq_pts_blds_left_flat + eq_pts_blds_right_flat) eq_pts_bbox = discretise_bbox(bbox) # Create the list with points for the voronoi diagram. vor_pts = eq_pts_road + eq_pts_blds_left_flat + eq_pts_blds_right_flat + eq_pts_bbox # Sometimes the library errors without a clear reason. In these cases # we set the class of the road segment to None. try: vor = VoronoiTess(vor_pts, add_bounding_box=False) except: print("Could not create Voronoi for this segment, id:", new_id) classification[new_id]['class'] = 'None' continue # Find the buildings facing the road for the left and right side. blds_left, blds_right, weights_left, weights_right = \ find_road_building_relations(vor, eq_pts_road, eq_pts_blds_left, eq_pts_blds_right, road_coords) road_to_building[new_id]['left'] = blds_left road_to_building[new_id]['right'] = blds_right # general: 21283, 27058, 27267, 28822 # voronoi column plots: 4269, 4270, 5811, 6283, 22841 if new_id in ('19662'): vor = Voronoi(vor_pts) sub_left = { k: blds_left_buffer[k] for k in road_to_building[new_id]['left'] } sub_right = { k: blds_right_buffer[k] for k in road_to_building[new_id]['right'] } # Get the classification for the given road segment and the points # beloning to that road segment if the ray-tracing option is used. if method in ('raytracing', 'raytracing_both'): classification[new_id]['class'], points_classified[new_id] = \ classify(method, building_data, blds_left, blds_right, weights_left, weights_right, road_part, points_classified[new_id]) else: classification[new_id]['class'] = classify( method, building_data, blds_left, blds_right, weights_left, weights_right, road_part, points_classified[new_id]) return classification, points_classified
def get_voronoi_dicts(structure, cutoff_radius=VORONOI_CUTOFF_RADIUS, cutoff_weight_fraction=VORONOI_CUTOFF_WEIGHT_FRACTION): voronoi_finder = VoronoiCoordFinder(structure) voronoi_finder.cutoff = cutoff_radius voronoi_finder_2 = VoronoiNN() voronoi_finder_2.cutoff = cutoff_radius all_neighbor_sites = {} all_neighbor_pairs = {} for center_site_index in range(0, len(structure.sites)): neighbor_sites_dict = {} neighbor_pairs_list = [] # print "center_site_index: ", center_site_index # Construct initial voronoi polyhedra using cutoff_radius neighborhood_sites = [structure[center_site_index] ] # begin list with center site polyhedra_sites = voronoi_finder.get_voronoi_polyhedra( center_site_index) polyhedra_sites_2 = voronoi_finder_2.get_voronoi_polyhedra( structure, center_site_index) cutoff_weight = cutoff_weight_fraction * sum(polyhedra_sites.values()) for neighbor_site, neighbor_weight in polyhedra_sites.items(): if neighbor_weight > cutoff_weight: neighborhood_sites.append(neighbor_site) # Re-tesselate only with sites that also meet cutoff_weight_fraction criteria voronoi_input_coords = [site.coords for site in neighborhood_sites] try: voronoi_tess = VoronoiTess(voronoi_input_coords) except IndexError: raise RuntimeError('VoronoiTess: details unknown') local_solid_angles = [] center_coords = structure[center_site_index].coords n_neighborhood_sites = len(neighborhood_sites) n_voronoi_vertices = len(voronoi_tess.vertices) neighbor_lookup = np.zeros(shape=(n_voronoi_vertices, n_voronoi_vertices, 2), dtype=np.int8) # Loop over neighbor sites (which surrond center_site) to: # - calculate solid angles # - construct neighbor_lookup array (which maps each voronoi edge to two adjacent neighbors) for neighbor_index in range(1, n_neighborhood_sites): facet_vertex_list = voronoi_tess.ridges[( 0, neighbor_index)] # 0 = center site if 0 in facet_vertex_list: raise RuntimeError( "Pathological structure: voronoi facet includes vertex at infinity" ) # Calculate solid angle of facet between center site and this neighbor site facet_coords = [ voronoi_tess.vertices[i] for i in facet_vertex_list ] local_solid_angles.append(solid_angle(center_coords, facet_coords)) # Add this voronoi ridge to neighbor_lookup array, to identify adjacent voronoi facets n_vertices = len(facet_vertex_list) for vertex1_index in range(0, n_vertices): vertex2_index = vertex1_index + 1 if vertex2_index == n_vertices: vertex2_index = 0 # wrap vertex2_index # Properly order vertex indicies to only use upper triangle of neighbor_lookup array (low_vert_index, high_vert_index) = (facet_vertex_list[vertex1_index], facet_vertex_list[vertex2_index]) if low_vert_index > high_vert_index: (low_vert_index, high_vert_index) = (high_vert_index, low_vert_index) # Store adjacent voronoi neighbors on different levels of neighbor_lookup, at location defined # by common voronoi edge running between low_vert_index (row) and high_vert_index (column). if neighbor_lookup[low_vert_index, high_vert_index, 0] == 0: neighbor_lookup[low_vert_index, high_vert_index, 0] = neighbor_index # first neighbor else: neighbor_lookup[low_vert_index, high_vert_index, 1] = neighbor_index # second neighbor # Loop over neighbor sites again to construct neighbor_sites_dict with solid angle weights max_local_solid_angle = max(local_solid_angles) for neighbor_index in range(1, n_neighborhood_sites): # Note: neighborhood_sites (which starts with center) is one longer than local_solid_angles neighbor_sites_dict[neighborhood_sites[neighbor_index]] = \ local_solid_angles[neighbor_index - 1] / max_local_solid_angle # Loop through upper triangle of neighbor_lookup and build a list of tuples of neighbor pair sites for low_vert_index in range(1, n_voronoi_vertices): for high_vert_index in range(low_vert_index + 1, n_voronoi_vertices): neighbor1_index = neighbor_lookup[low_vert_index, high_vert_index, 0] neighbor2_index = neighbor_lookup[low_vert_index, high_vert_index, 1] if neighbor1_index > 0 and neighbor2_index > 0: # Both are non-zero neighbor_pairs_list.append( (neighborhood_sites[neighbor1_index], neighborhood_sites[neighbor2_index])) elif neighbor1_index != 0 or neighbor2_index != 0: # Only one is non-zero raise RuntimeError( "Unexpected neighbor_lookup matrix: non-paired edge") # Append per site values all_neighbor_sites[ structure.sites[center_site_index]] = neighbor_sites_dict all_neighbor_pairs[ structure.sites[center_site_index]] = neighbor_pairs_list return (all_neighbor_sites, all_neighbor_pairs)
def get_voronoi_dicts_2(structure, cutoff_radius=VORONOI_CUTOFF_RADIUS, cutoff_weight_fraction=VORONOI_CUTOFF_WEIGHT_FRACTION): voronoi_finder_2 = VoronoiNN() voronoi_finder_2.cutoff = cutoff_radius all_neighbor_sites = {} all_neighbor_pairs = {} for center_site_index in range(0, len(structure.sites)): neighbor_sites_dict = {} neighbor_pairs_list = [] neighborhood_sites = [structure[center_site_index]] sites_property = voronoi_finder_2.get_nn_info(structure, center_site_index) cutoff_weight = cutoff_weight_fraction * sum( voronoi_finder_2.get_weights_of_nn_sites(structure, center_site_index)) for neighbor_index in range(0, len(sites_property)): neighbor_weight = voronoi_finder_2.get_nn_info( structure, center_site_index)[neighbor_index]['weight'] neighbor_site = voronoi_finder_2.get_nn_info( structure, center_site_index)[neighbor_index]['site'] if neighbor_weight > cutoff_weight: neighborhood_sites.append(neighbor_site) neighbor_sites_dict[neighbor_site] = neighbor_weight # Re-tesselate only with sites that also meet cutoff_weight_fraction criteria voronoi_input_coords = [site.coords for site in neighborhood_sites] try: voronoi_tess = VoronoiTess(voronoi_input_coords) except IndexError: raise RuntimeError('VoronoiTess: details unknown') n_neighborhood_sites = len(neighborhood_sites) n_voronoi_vertices = len(voronoi_tess.vertices) neighbor_lookup = np.zeros(shape=(n_voronoi_vertices, n_voronoi_vertices, 2), dtype=np.int8) # Loop over neighbor sites (which surrond center_site) to: # - calculate solid angles # - construct neighbor_lookup array (which maps each voronoi edge to two adjacent neighbors) for neighbor_index in range(1, n_neighborhood_sites): facet_vertex_list = voronoi_tess.ridges[( 0, neighbor_index)] # 0 = center site if 0 in facet_vertex_list: raise RuntimeError( "Pathological structure: voronoi facet includes vertex at infinity" ) # Add this voronoi ridge to neighbor_lookup array, to identify adjacent voronoi facets n_vertices = len(facet_vertex_list) for vertex1_index in range(0, n_vertices): vertex2_index = vertex1_index + 1 if vertex2_index == n_vertices: vertex2_index = 0 # wrap vertex2_index # Properly order vertex indicies to only use upper triangle of neighbor_lookup array (low_vert_index, high_vert_index) = (facet_vertex_list[vertex1_index], facet_vertex_list[vertex2_index]) if low_vert_index > high_vert_index: (low_vert_index, high_vert_index) = (high_vert_index, low_vert_index) # Store adjacent voronoi neighbors on different levels of neighbor_lookup, at location defined # by common voronoi edge running between low_vert_index (row) and high_vert_index (column). if neighbor_lookup[low_vert_index, high_vert_index, 0] == 0: neighbor_lookup[low_vert_index, high_vert_index, 0] = neighbor_index # first neighbor else: neighbor_lookup[low_vert_index, high_vert_index, 1] = neighbor_index # second neighbor # Loop through upper triangle of neighbor_lookup and build a list of tuples of neighbor pair sites for low_vert_index in range(1, n_voronoi_vertices): for high_vert_index in range(low_vert_index + 1, n_voronoi_vertices): neighbor1_index = neighbor_lookup[low_vert_index, high_vert_index, 0] neighbor2_index = neighbor_lookup[low_vert_index, high_vert_index, 1] if neighbor1_index > 0 and neighbor2_index > 0: # Both are non-zero neighbor_pairs_list.append( (neighborhood_sites[neighbor1_index], neighborhood_sites[neighbor2_index])) elif neighbor1_index != 0 or neighbor2_index != 0: # Only one is non-zero raise RuntimeError( "Unexpected neighbor_lookup matrix: non-paired edge") # Append per site values all_neighbor_sites[ structure.sites[center_site_index]] = neighbor_sites_dict all_neighbor_pairs[ structure.sites[center_site_index]] = neighbor_pairs_list return (all_neighbor_sites, all_neighbor_pairs)
def voroArea(Atoms, qry, size_x, size_y): orgCRDs = Atoms.coordinates() #convert 3D to 2D: extractig X and Y axis orgCRDs = selCoord(orgCRDs, [0, 1]) orgPoints = getNumPoints(Atoms, qry) uq_resNames = orgPoints[0] # Residues names in the given system uq_numAtoms = orgPoints[1] # the number of selected atoms corresponding to residue names #------------------------------- # calculating image boxes # 5 | 3 | 7 # 1 | primary 0 | 2 # 6 | 4 | 8 #------------------------------- sysCRDs = mkimagebox(orgCRDs, size_x, size_y) # calculating voronoi tessellation voro = VoronoiTess(sysCRDs) voro_vtex = voro.vertices voro_regn = voro.regions # calculating area per lipids resIDs = Atoms.resids() # obtaining residue ids resNames = Atoms.resnames() # initializing array areaLipids = [0.0] * (len(resIDs) + 1) # each array will be used for individual lipid area and last one will be the average area res_cnt = 0 # residue count num_atoms = 0 # number of atoms corresponding to the current residue name crd_idx = 0 # coordinate index M = numpy.array(sysCRDs) max_x = M.max(axis=0)[0] / 2.0 max_y = M.max(axis=0)[1] / 2.0 min_x = M.min(axis=0)[0] / 2.0 min_y = M.min(axis=0)[1] / 2.0 for res_name in resNames: # find corresponding residue num_atoms = uq_numAtoms[uq_resNames.index(res_name)] #print resNames; #calculating the area corresponding to the point atom_cnt = 0 myarea = 0.0 for dummy in range(num_atoms): #print "max_x={}, max_y={}, min_x={}, min_y={}".format(max_x, max_y, min_x, min_y); #print "crdIdx:{0}, lenRegio:{1}, len(CRDs):{2}, residue:{3}, num_atoms:{4}, num_residue:{5}".format(crd_idx, len(voro_regn), len(orgCRDs), res_name, num_atoms, len(resNames)); if crd_idx >= len(orgCRDs): break else: my_region = getPos(voro_regn[crd_idx]) liparea = crdArea(my_region, voro_vtex, max_x, max_y, min_x, min_y) #print "crd_idx={}, res_name ={}, res_ID={}, X={}, Y={}".format(crd_idx, res_name, resIDs[res_cnt], sysCRDs[crd_idx][0], sysCRDs[crd_idx][1]); crd_idx = crd_idx + 1 myarea = myarea + liparea areaLipids[res_cnt] = myarea res_cnt = res_cnt + 1 areaLipids[len(areaLipids) - 1] = sum(areaLipids) / res_cnt #print "len(areaLipids): {}, len(orgCRDs): {}".format(len(areaLipids), len(orgCRDs)); return areaLipids
legkeys.append(p) legitems.append("Delaunay tri") d = ConvexHull(points) for s in d.simplices: for data in itertools.combinations(s.coords, dim): data = np.array(data) p, = plt.plot(data[:,0], data[:,1], 'b-') if dim == 2 else\ ax.plot(data[:,0], data[:,1], data[:,2], 'b-') legkeys.append(p) legitems.append("Convex hull") if dim == 2: d = VoronoiTess(points) points = d.points avg = np.average(points, 0) vertices = d.vertices for nn, vind in d.ridges.items(): (i1, i2) = sorted(vind) if i1 == 0: c1 = np.array(vertices[i2]) midpt = 0.5 * (np.array(points[nn[0]]) + np.array(points[nn[1]])) if np.dot(avg - midpt, c1 - midpt) > 0: c2 = c1 + 10 * (midpt - c1) else: c2 = c1 - 10 * (midpt - c1) p1, = plt.plot([c1[0], c2[0]], [c1[1], c2[1]], 'k--') else: c1 = vertices[i1]
def generate_hexagonal(nx, ny): """Create a hexagonal mesh of dimension nx x ny. Parameters ---------- nx : int Number of cells in x direction ny : int Number of cells in y direction Returns ------- mesh : Mesh type hexagonal mesh of dimension nx, ny """ # We specifiy the dimension of the grid in x and y direction number_of_cells = np.array((nx, ny)) number_of_cells_and_dummies = number_of_cells + 2 # We make a mesh of cell centroids centroid_positions = np.zeros((number_of_cells_and_dummies.prod(), 2), 'double') origin = -number_of_cells_and_dummies / 2.0 + 0.5 counter = 0 for x_index in range(number_of_cells_and_dummies[0]): for y_index in range(number_of_cells_and_dummies[1]): if y_index % 2 == 0: centroid_positions[counter, 0] = origin[0] + x_index * 1.0 else: centroid_positions[counter, 0] = origin[0] + 0.5 + x_index * 1.0 centroid_positions[counter, 1] = origin[1] + y_index * 1.0 counter += 1 # We generate a Voronoi tesselation of that voronoi_diagram = VoronoiTess(centroid_positions) # Now, let's get all vertices all_vertices = np.array(voronoi_diagram.vertices) # and all regions all_regions = voronoi_diagram.regions # now, let's make a new array of vertices and a new array of regions new_vertices = [] new_elements = [] index_map = [-1] * all_vertices.shape[0] current_number_of_new_vertices = 0 # Loop over all regions for region in all_regions: # If this region is not a boundary region if (0 not in region) and (len(region) == 6): # then we want to keep it new_region = [] for index in region: # if the index is not in the new vertices, add it if (index_map[index] == -1): this_node = Node(all_vertices[index]) new_vertices.append(this_node) index_map[index] = current_number_of_new_vertices # and add it to the new region new_region.append(this_node) current_number_of_new_vertices += 1 else: # if it is in the new vertices though then add # the right vertex to the new region new_region.append(new_vertices[index_map[index]]) # lets make an element from that region and add it to the list of elements new_elements.append(Element(new_region)) # ensure that all the vertices in each element are ordered counterclockwise for element in new_elements: area = element.calculate_area() if area < 0: element.nodes.reverse() area = element.calculate_area() assert (abs(area - 1.0) < 1e-10) # now we can create a mesh and return it return Mesh(new_vertices, new_elements)