Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
Returns
-------
ndarray of int
The link ID as the nth vertical links.
Examples
--------
>>> from landlab.grid.structured_quad.links import nth_vertical_link
>>> shape = (3, 4)
>>> nth_vertical_link(shape, 4)
1
>>> nth_vertical_link(shape, (3, 4, 11))
array([0, 1, 5])
"""
links = np.asarray(links, dtype=np.int)
return as_id_array(
(links // (2 * shape[1] - 1)) * shape[1]
+ links % (2 * shape[1] - 1)
- (shape[1] - 1)
)
Returns
-------
ndarray of int
The link ID as the nth horizontal links.
Examples
--------
>>> from landlab.components.overland_flow._links import nth_horizontal_link
>>> shape = (3, 4)
>>> nth_horizontal_link(shape, 16)
8
>>> nth_horizontal_link(shape, (1, 7, 8))
array([1, 3, 4])
"""
links = np.asarray(links, dtype=np.int)
return as_id_array(
(links // (2 * shape[1] - 1)) * (shape[1] - 1) + links % (2 * shape[1] - 1)
)
def sort(self):
from .sort.ext.remap_element import remap_graph_element
sorted_nodes, sorted_links, sorted_patches = Graph.sort(self)
sorted_corners, sorted_faces, sorted_cells = self.dual.sort()
with self.thawed():
self.node_at_cell[:] = self.node_at_cell[sorted_cells]
self.nodes_at_face[:] = self.nodes_at_face[sorted_faces]
remap_graph_element(
as_id_array(self.node_at_cell), as_id_array(np.argsort(sorted_nodes))
)
remap_graph_element(
as_id_array(self.nodes_at_face).reshape((-1,)),
as_id_array(np.argsort(sorted_nodes)),
)
ndarray :
Number of links leaving nodes.
Examples
--------
>>> from landlab.grid.unstructured.links import out_link_count_per_node
>>> out_link_count_per_node(([0, 1, 2, 3, 4, 5], [3, 4, 5, 6, 7, 8]))
array([1, 1, 1, 1, 1, 1])
>>> out_link_count_per_node(([0, 1, 2, 3, 4, 5], [3, 4, 5, 6, 7, 8]),
... number_of_nodes=9)
array([1, 1, 1, 1, 1, 1, 0, 0, 0])
"""
node_at_link_start, node_at_link_end = _split_link_ends(node_at_link_ends)
if len(node_at_link_end) != len(node_at_link_start):
raise ValueError("Link arrays must be the same length")
return as_id_array(np.bincount(node_at_link_start, minlength=number_of_nodes))
def _create_patches_from_delaunay_diagram(self, pts, vor):
"""
Uses a delaunay diagram drawn from the provided points to
generate an array of patches and patch-node-link connectivity.
Returns ...
DEJH, 10/3/14, modified May 16.
"""
from scipy.spatial import Delaunay
from landlab.core.utils import anticlockwise_argsort_points_multiline
from .cfuncs import find_rows_containing_ID, \
create_patches_at_element, create_links_at_patch
tri = Delaunay(pts)
assert np.array_equal(tri.points, vor.points)
nodata = -1
self._nodes_at_patch = as_id_array(tri.simplices)
# self._nodes_at_patch = np.empty_like(_nodes_at_patch)
self._number_of_patches = tri.simplices.shape[0]
# get the patches in order:
patches_xy = np.empty((self._number_of_patches, 2), dtype=float)
patches_xy[:, 0] = np.mean(self.node_x[self._nodes_at_patch],
axis=1)
patches_xy[:, 1] = np.mean(self.node_y[self._nodes_at_patch],
axis=1)
orderforsort = argsort_points_by_x_then_y(patches_xy)
self._nodes_at_patch = self._nodes_at_patch[orderforsort, :]
patches_xy = patches_xy[orderforsort, :]
# get the nodes around the patch in order:
nodes_xy = np.empty((3, 2), dtype=float)
# perform a CCW sort without a line-by-line loop:
patch_nodes_x = self.node_x[self._nodes_at_patch]
# step 2b. Run depression finder if passed
# Depression finder reaccumulates flow at the end of its routine.
# At the moment, no depression finders work with to-many, so it
# lives here
if self._depression_finder_provided is not None:
self._depression_finder.map_depressions()
# if FlowDirectorSteepest is used, update the link directions
if self._flow_director._name == "FlowDirectorSteepest":
self._flow_director._determine_link_directions()
# step 3. Stack, D, delta construction
nd = as_id_array(flow_accum_bw._make_number_of_donors_array(r))
delta = as_id_array(flow_accum_bw._make_delta_array(nd))
D = as_id_array(flow_accum_bw._make_array_of_donors(r, delta))
s = as_id_array(flow_accum_bw.make_ordered_node_array(r))
# put these in grid so that depression finder can use it.
# store the generated data in the grid
self._grid.at_node["flow__data_structure_delta"][:] = delta[1:]
self._D_structure = D
self._grid.at_node["flow__upstream_node_order"][:] = s
# step 4. Accumulate (to one or to N depending on direction method)
a[:], q[:] = self._accumulate_A_Q_to_one(s, r)
else:
# Get p
p = self._grid["node"]["flow__receiver_proportions"]
# step 3. Stack, D, delta construction
# perform a CCW sort without a line-by-line loop:
patch_nodes_x = self.node_x[self._nodes_at_patch]
patch_nodes_y = self.node_y[self._nodes_at_patch]
anticlockwise_argsort_points_multiline(patch_nodes_x, patch_nodes_y,
out=self._nodes_at_patch)
# need to build a squared off, masked array of the patches_at_node
# the max number of patches for a node in the grid is the max sides of
# the side-iest voronoi region.
max_dimension = len(max(vor.regions, key=len))
self._patches_at_node = np.full(
(self.number_of_nodes, max_dimension), nodata, dtype=int)
self._nodes_at_patch = as_id_array(self._nodes_at_patch)
self._patches_at_node = as_id_array(self._patches_at_node)
create_patches_at_element(self._nodes_at_patch,
self.number_of_nodes,
self._patches_at_node)
# build the patch-link connectivity:
self._links_at_patch = np.empty((self._number_of_patches, 3),
dtype=int)
create_links_at_patch(self._nodes_at_patch, self._links_at_node,
self._number_of_patches, self._links_at_patch)
patch_links_x = self.x_of_link[self._links_at_patch]
patch_links_y = self.y_of_link[self._links_at_patch]
anticlockwise_argsort_points_multiline(patch_links_x, patch_links_y,
out=self._links_at_patch)
# set() function to turn the array into a set, which removes duplicate
# vertices. Then we turn it back into an array, which now contains the
# set of IDs for the nodes that make up the convex hull.
# The next thing to worry about is the fact that the mesh perimeter
# might contain nodes that are co-planar (that is, co-linear in our 2D
# world). For example, if you make a set of staggered points for a
# hexagonal lattice using make_hex_points(), there will be some
# co-linear points along the perimeter. The ones of these that don't
# form convex corners won't be included in convex_hull_nodes, but they
# are nonetheless part of the perimeter and need to be included in
# the list of boundary_nodes. To deal with this, we pass the 'Qt'
# option to ConvexHull, which makes it generate a list of coplanar
# points. We include these in our set of boundary nodes.
convex_hull_nodes = np.array(list(set(hull.simplices.flatten())))
coplanar_nodes = hull.coplanar[:, 0]
boundary_nodes = as_id_array(np.concatenate(
(convex_hull_nodes, coplanar_nodes)))
# Now we'll create the "node_status" array, which contains the code
# indicating whether the node is interior and active (=0) or a
# boundary (=1). This means that all perimeter (convex hull) nodes are
# initially flagged as boundary code 1. An application might wish to
# change this so that, for example, some boundaries are inactive.
node_status = np.zeros(len(pts[:, 0]), dtype=np.uint8)
node_status[boundary_nodes] = 1
# It's also useful to have a list of interior nodes
core_nodes = as_id_array(np.where(node_status == 0)[0])
# save the arrays and update the properties
self._node_status = node_status
self._node_at_cell = core_nodes
# perform a CCW sort without a line-by-line loop:
patch_nodes_x = self.node_x[self._nodes_at_patch]
patch_nodes_y = self.node_y[self._nodes_at_patch]
anticlockwise_argsort_points_multiline(patch_nodes_x, patch_nodes_y,
out=self._nodes_at_patch)
# need to build a squared off, masked array of the patches_at_node
# the max number of patches for a node in the grid is the max sides of
# the side-iest voronoi region.
max_dimension = len(max(vor.regions, key=len))
self._patches_at_node = np.full(
(self.number_of_nodes, max_dimension), nodata, dtype=int)
self._nodes_at_patch = as_id_array(self._nodes_at_patch)
self._patches_at_node = as_id_array(self._patches_at_node)
create_patches_at_element(self._nodes_at_patch,
self.number_of_nodes,
self._patches_at_node)
# build the patch-link connectivity:
self._links_at_patch = np.empty((self._number_of_patches, 3),
dtype=int)
create_links_at_patch(self._nodes_at_patch, self._links_at_node,
self._number_of_patches, self._links_at_patch)
patch_links_x = self.x_of_link[self._links_at_patch]
patch_links_y = self.y_of_link[self._links_at_patch]
anticlockwise_argsort_points_multiline(patch_links_x, patch_links_y,
out=self._links_at_patch)
self._patches_at_link = np.empty((self.number_of_links, 2),
def reindex_links_by_xy(graph):
from ..quantity.of_link import get_midpoint_of_link
from .ext.remap_element import remap_graph_element_ignore
xy_of_link = get_midpoint_of_link(graph)
sorted_links = argsort_points_by_x_then_y(xy_of_link)
# graph._nodes_at_link[:] = graph._nodes_at_link[sorted_links, :]
graph.nodes_at_link[:] = graph.nodes_at_link[sorted_links, :]
# if hasattr(graph, '_links_at_patch'):
if "links_at_patch" in graph.ds:
remap_graph_element_ignore(
graph.links_at_patch.reshape((-1,)),
as_id_array(np.argsort(sorted_links)),
-1,
)
return sorted_links