Skip to content

link_counts

Get the link-type counts of a geodataframe given a spatial weights object w.

Parameters:

Name Type Description Default
gdf GeoDataFrame

Input geodataframe. Has to have a class_name column.

required
w W

Libpysal spatial weights object of the gdf.

required
classes Tuple[str, ...]

A list/tuple containing the classes of your dataset.

required

Returns:

Type Description
Dict[str, int]

Dict[str, int]: A contigency dictionary.

Examples:

Get the link types of the tumor-stroma interfaces.

>>> from cellseg_gsontools.spatial_context import InterfaceContext
>>> from cellseg_gsontools.links import link_counts
>>> iface_context = InterfaceContext(
...     area_gdf=areas,
...     cell_gdf=cells,
...     top_labels="area_cin",
...     bottom_labels="areastroma",
...     silence_warnings=True,
...     min_area_size=100000.0,
... )
>>> classes = [
...     "inflammatory",
...     "connective",
...     "glandular_epithel",
...     "squamous_epithel",
...     "neoplastic",
... ]
>>> iface_context.fit(verbose=False)
>>> w = iface_context.context2weights("border_network")
>>> link_counts(cells, w, classes)
{'inflammatory-inflammatory': 31,
'inflammatory-connective': 89,
'inflammatory-glandular_epithel': 0,
'inflammatory-squamous_epithel': 0,
'inflammatory-neoplastic': 86,
'connective-connective': 131,
'connective-glandular_epithel': 0,
'connective-squamous_epithel': 0,
'connective-neoplastic': 284,
'glandular_epithel-glandular_epithel': 0,
'glandular_epithel-squamous_epithel': 0,
'glandular_epithel-neoplastic': 0,
'squamous_epithel-squamous_epithel': 0,
'squamous_epithel-neoplastic': 0,
'neoplastic-neoplastic': 236}
Source code in cellseg_gsontools/links.py
def link_counts(
    gdf: gpd.GeoDataFrame, w: W, classes: Tuple[str, ...]
) -> Dict[str, int]:
    """Get the link-type counts of a geodataframe given a spatial weights object `w`.

    Parameters:
        gdf (gpd.GeoDataFrame):
            Input geodataframe. Has to have a `class_name` column.
        w (libysal.weights.W):
            Libpysal spatial weights object of the gdf.
        classes (Tuple[str, ...]):
            A list/tuple containing the classes of your dataset.

    Returns:
        Dict[str, int]:
            A contigency dictionary.

    Examples:
        Get the link types of the tumor-stroma interfaces.
        >>> from cellseg_gsontools.spatial_context import InterfaceContext
        >>> from cellseg_gsontools.links import link_counts
        >>> iface_context = InterfaceContext(
        ...     area_gdf=areas,
        ...     cell_gdf=cells,
        ...     top_labels="area_cin",
        ...     bottom_labels="areastroma",
        ...     silence_warnings=True,
        ...     min_area_size=100000.0,
        ... )
        >>> classes = [
        ...     "inflammatory",
        ...     "connective",
        ...     "glandular_epithel",
        ...     "squamous_epithel",
        ...     "neoplastic",
        ... ]
        >>> iface_context.fit(verbose=False)
        >>> w = iface_context.context2weights("border_network")
        >>> link_counts(cells, w, classes)
        {'inflammatory-inflammatory': 31,
        'inflammatory-connective': 89,
        'inflammatory-glandular_epithel': 0,
        'inflammatory-squamous_epithel': 0,
        'inflammatory-neoplastic': 86,
        'connective-connective': 131,
        'connective-glandular_epithel': 0,
        'connective-squamous_epithel': 0,
        'connective-neoplastic': 284,
        'glandular_epithel-glandular_epithel': 0,
        'glandular_epithel-squamous_epithel': 0,
        'glandular_epithel-neoplastic': 0,
        'squamous_epithel-squamous_epithel': 0,
        'squamous_epithel-neoplastic': 0,
        'neoplastic-neoplastic': 236}
    """
    combos = get_link_combinations(classes)
    link_cnt = {combo: 0 for combo in combos}

    all_node_pairs = []
    for node, neighbors in w.neighbors.items():
        ncls = gdf.loc[node, "class_name"]
        if neighbors:
            neighbors_cls = gdf.loc[neighbors, "class_name"]
            node_pairs = [set((node, n)) for n in neighbors]

            for ngh_ix, ngh_cls in zip(neighbors, neighbors_cls):
                node_ids = set((node, ngh_ix))
                if node_ids not in all_node_pairs:
                    for combo in combos:
                        types = set(combo.split("-"))
                        if ncls in types and ngh_cls in types and ngh_cls != ncls:
                            link_cnt[combo] += 1
                        elif ncls in types and ngh_cls in types and ngh_cls == ncls:
                            if len(types) == 1:
                                link_cnt[combo] += 1

            all_node_pairs.extend(node_pairs)

    return link_cnt