Example #1
0
    def nodes_kdtree(self, only_coords=False):
        """

        Build a kdtree from the network node coords for observations lookup.

        Parameters
        ----------

        only_coords : bool
            Flag for only coordinated being passed in.

        Returns
        -------
        kdtree : scipy.spatial.kdtree.KDTree
            All network nodes lookup.

        """

        if only_coords:
            geoms = self.n_data[self.geo_col]
            coords = list(zip(geoms.x, geoms.y))
            kdtree = cg.KDTree(coords)
        else:
            coords = [
                coords[0] for (node, coords) in list(self.node2coords.items())
            ]
            kdtree = cg.KDTree(coords)

        return kdtree
def build_net_nodes_kdtree(nodes, only_coords=False):
    """build a kdtree from the network node coords for
    point pattern lookup
    
    Parameters
    ----------
    node : either nodes2coords dictionary or coords list
    only_coords : bool
    
    Returns
    -------
    net_nodes_kdtree : scipy.spatial.kdtree.KDTree
        all network nodes lookup
    """

    if only_coords:
        return cg.KDTree(nodes)

    else:
        if type(nodes) is dict:
            node_coords = [coords[0] for node, coords in list(nodes.items())]
        elif type(nodes) is list:
            node_coords = [coords[0] for (node, coords) in nodes]

    net_nodes_kdtree = cg.KDTree(node_coords)

    return net_nodes_kdtree
Example #3
0
def snap_points_to_links(points, links):
    """Place points onto closest link in a set of links
    (arc/edges)
    
    Parameters
    ----------
    
    points : dict
        Point id as key and (x,y) coordinate as value
    
    links : list
        Elements are of type libpysal.cg.shapes.Chain
        ** Note ** each element is a links represented as a chain with
        *one head and one tail vertex* in other words one link only.
    
    Returns
    -------
    
    point2link : dict
        key [point id (see points in arguments)]; value [a 2-tuple 
        ((head, tail), point) where (head, tail) is the target link,
        and point is the snapped location on the link.
    
    Examples
    --------
    
    >>> import spaghetti as spgh
    >>> from libpysal.cg.shapes import Point, Chain
    >>> points = {0: Point((1,1))}
    >>> link = [Chain([Point((0,0)), Point((2,0))])]
    >>> spgh.util.snap_points_to_links(points, link)
    {0: ([(0.0, 0.0), (2.0, 0.0)], array([1., 0.]))}
    
    """

    # instantiate an rtree
    rtree = cg.Rtree()
    # set the smallest possible float epsilon on machine
    SMALL = np.finfo(float).eps

    # initialize network vertex to link lookup
    vertex_2_link = {}

    # iterate over network links
    for link in links:

        # extract network link (x,y) vertex coordinates
        head, tail = link.vertices
        x0, y0 = head
        x1, y1 = tail

        if (x0, y0) not in vertex_2_link:
            vertex_2_link[(x0, y0)] = []

        if (x1, y1) not in vertex_2_link:
            vertex_2_link[(x1, y1)] = []

        vertex_2_link[(x0, y0)].append(link)
        vertex_2_link[(x1, y1)].append(link)

        # minimally increase the bounding box exterior
        bx0, by0, bx1, by1 = link.bounding_box
        bx0 -= SMALL
        by0 -= SMALL
        bx1 += SMALL
        by1 += SMALL

        # create a rectangle
        rect = cg.Rect(bx0, by0, bx1, by1)

        # insert the network link and its associated
        # rectangle into the rtree
        rtree.insert(link, rect)

    # build a KDtree on link vertices
    kdtree = cg.KDTree(list(vertex_2_link.keys()))

    point2link = {}

    for pt_idx, point in points.items():

        # first, find nearest neighbor link vertices for the point
        dmin, vertex = kdtree.query(point, k=1)
        vertex = tuple(kdtree.data[vertex])
        closest = vertex_2_link[vertex][0].vertices

        # Use this link as the candidate closest link:  closest
        # Use the distance as the distance to beat:     dmin
        point2link[pt_idx] = (closest, np.array(vertex))
        x0 = point[0] - dmin
        y0 = point[1] - dmin
        x1 = point[0] + dmin
        y1 = point[1] + dmin

        # Find all links with bounding boxes that intersect
        # a query rectangle centered on the point with sides
        # of length dmin * dmin
        candidates = [cand for cand in rtree.intersection([x0, y0, x1, y1])]
        dmin += SMALL
        dmin2 = dmin * dmin

        # of the candidate arcs, find the nearest to the query point
        for candidate in candidates:
            dist2cand, nearp = squared_distance_point_link(
                point, candidate.vertices)
            if dist2cand <= dmin2:
                closest = candidate.vertices
                dmin2 = dist2cand
                point2link[pt_idx] = (closest, nearp)

    return point2link
Example #4
0
def knox(s_coords, t_coords, delta, tau, permutations=99, debug=False):
    """
    Knox test for spatio-temporal interaction. :cite:`Knox:1964`

    Parameters
    ----------
    s_coords        : array
                      (n, 2), spatial coordinates.
    t_coords        : array
                      (n, 1), temporal coordinates.
    delta           : float
                      threshold for proximity in space.
    tau             : float
                      threshold for proximity in time.
    permutations    : int, optional
                      the number of permutations used to establish pseudo-
                      significance (the default is 99).
    debug           : bool, optional
                      if true, debugging information is printed (the default is
                      False).

    Returns
    -------
    knox_result     : dictionary
                      contains the statistic (stat) for the test and the
                      associated p-value (pvalue).
    stat            : float
                      value of the knox test for the dataset.
    pvalue          : float
                      pseudo p-value associated with the statistic.
    counts          : int
                      count of space time neighbors.

    Examples
    --------
    >>> import numpy as np
    >>> import libpysal as lps
    >>> from pointpats import SpaceTimeEvents, knox

    Read in the example data and create an instance of SpaceTimeEvents.

    >>> path = lps.examples.get_path("burkitt.shp")
    >>> events = SpaceTimeEvents(path,'T')

    Set the random seed generator. This is used by the permutation based
    inference to replicate the pseudo-significance of our example results -
    the end-user will normally omit this step.

    >>> np.random.seed(100)

    Run the Knox test with distance and time thresholds of 20 and 5,
    respectively. This counts the events that are closer than 20 units in
    space, and 5 units in time.

    >>> result = knox(events.space, events.t, delta=20, tau=5, permutations=99)

    Next, we examine the results. First, we call the statistic from the
    results dictionary. This reports that there are 13 events close
    in both space and time, according to our threshold definitions.

    >>> result['stat'] == 13
    True

    Next, we look at the pseudo-significance of this value, calculated by
    permuting the timestamps and rerunning the statistics. In this case,
    the results indicate there is likely no space-time interaction between
    the events.

    >>> print("%2.2f"%result['pvalue'])
    0.17
    """

    # Do a kdtree on space first as the number of ties (identical points) is
    # likely to be lower for space than time.

    kd_s = cg.KDTree(s_coords)
    neigh_s = kd_s.query_pairs(delta)
    tau2 = tau * tau
    ids = np.array(list(neigh_s))

    # For the neighboring pairs in space, determine which are also time
    # neighbors

    d_t = (t_coords[ids[:, 0]] - t_coords[ids[:, 1]])**2
    n_st = sum(d_t <= tau2)

    knox_result = {'stat': n_st[0]}

    if permutations:
        joint = np.zeros((permutations, 1), int)
        for p in range(permutations):
            np.random.shuffle(t_coords)
            d_t = (t_coords[ids[:, 0]] - t_coords[ids[:, 1]])**2
            joint[p] = np.sum(d_t <= tau2)

        larger = sum(joint >= n_st[0])
        if (permutations - larger) < larger:
            larger = permutations - larger
        p_sim = (larger + 1.) / (permutations + 1.)
        knox_result['pvalue'] = p_sim
    return knox_result
Example #5
0
def snap_points_on_segments(points, segments):
    """Place points onto closet segment in a set of segments
    
    Parameters
    ----------
    
    points : dict
        Point id as key and (x,y) coordinate as value
    
    segments : list
        Elements are of type libpysal.cg.shapes.Chain
        ** Note ** each element is a segment represented as a chain with
        *one head and one tail node* in other words one link only.
    
    Returns
    -------
    
    p2s : dict
        key [point id (see points in arguments)]; value [a 2-tuple 
        ((head, tail), point) where (head, tail) is the target segment,
        and point is the snapped location on the segment.
    
    Examples
    --------
    
    >>> import spaghetti as spgh
    >>> from libpysal.cg.shapes import Point, Chain
    >>> points = {0: Point((1,1))}
    >>> segments = [Chain([Point((0,0)), Point((2,0))])]
    >>> spgh.util.snap_points_on_segments(points, segments)
    {0: ([(0.0, 0.0), (2.0, 0.0)], array([1., 0.]))}
    """

    # Put segments in an Rtree.
    rt = cg.Rtree()
    SMALL = np.finfo(float).eps
    node2segs = {}

    for segment in segments:
        head, tail = segment.vertices
        x0, y0 = head
        x1, y1 = tail
        if (x0, y0) not in node2segs:
            node2segs[(x0, y0)] = []
        if (x1, y1) not in node2segs:
            node2segs[(x1, y1)] = []
        node2segs[(x0, y0)].append(segment)
        node2segs[(x1, y1)].append(segment)
        x0, y0, x1, y1 = segment.bounding_box
        x0 -= SMALL
        y0 -= SMALL
        x1 += SMALL
        y1 += SMALL
        r = cg.Rect(x0, y0, x1, y1)
        rt.insert(segment, r)

    # Build a KDtree on segment nodes.
    kt = cg.KDTree(list(node2segs.keys()))
    p2s = {}

    for ptIdx, point in points.items():
        # First, find nearest neighbor segment node for the point.
        dmin, node = kt.query(point, k=1)
        node = tuple(kt.data[node])
        closest = node2segs[node][0].vertices

        # Use this segment as the candidate closest segment:  closest
        # Use the distance as the distance to beat:           dmin
        p2s[ptIdx] = (closest, np.array(node))
        x0 = point[0] - dmin
        y0 = point[1] - dmin
        x1 = point[0] + dmin
        y1 = point[1] + dmin

        # Find all segments with bounding boxes that intersect
        # a query rectangle centered on the point with sides of length 2*dmin.
        candidates = [cand for cand in rt.intersection([x0, y0, x1, y1])]
        dmin += SMALL
        dmin2 = dmin * dmin

        # Of the candidate segments, find the nearest to the query point.
        for candidate in candidates:
            dnc, p2b = squared_distance_point_segment(point,
                                                      candidate.vertices)
            if dnc <= dmin2:
                closest = candidate.vertices
                dmin2 = dnc
                p2s[ptIdx] = (closest, p2b)

    return p2s