TissueGraph implementation proposal

Biological observations

The typical object is a multicellular tissue observation (from microscopy). Cell-based segmentation, manual or algorithmic, is required to access the spatial information hidden in the intensity image.

Goal

The goal of this data structure is to provide a flexible graph object dedicated to the organisation and exploration of multicellular tissue properties.

  • It is based on the networkx library.

  • Biological semantic should be used when possible.

  • Properties are stored in dictionaries attached to the corresponding element, i.e. the volume of a cell will be attached to the cell

Structure

A primal graph organize the cells (primal graph nodes) and connect them with walls (primal graph edges). A dual graph organize the cell vertices (dual graph nodes) and connect them with cell edges (dual graph edges).

Both graphs are undirected networkx.Graph().

Warning

We have to define what to do with the background id!

Element ids

Tissue image element ids

In the image, the topological element ids are:

  • cell ids are defined by an integer, e.g. 5.

  • cell-wall ids are defined by two cells in junction, so a len-2 tuple of integers, e.g. (5, 6) for cells 5 and 6.

  • cell-edge ids are defined by three cells in junction, so a len-3 tuple of integers, e.g. (5, 6, 7) for cells 5, 6 and 7.

  • cell-vertex ids are defined by four cells in junction, so a len-4 tuple of integers, e.g. (5, 6, 7, 8) for cells 5, 6, 7 and 8.

Tissue graph element ids

In the tissue graph, the topological element ids are different for edges as they now relate two cell-vertices of the dual graph.

Primal graph

  • cell ids cid are the nodes defined by integers, e.g. 5 for cell 5.

  • cell-wall ids wid=(cid_i, cid_j) are the edges defined by a len-2 tuple of integers, e.g. (5, 6) for the two cells (nodes) it join.

Dual graph

  • cell-vertex ids vid=(cid_i, cid_j, cid_k, cid_l) are the nodes defined by a len-4 tuple of integers, e.g. (5, 6, 7, 8) for cells 5, 6, 7 and 8.

  • cell-edge ids eid=(vid_1, vid_2)=((cid_i1, cid_j1, cid_k1, cid_l1), (cid_i2, cid_j2, cid_k2, cid_l2)) are the edges defined by two len-4 tuple of integers, e.g. (5, 6, 7, 8) and (5, 6, 7, 9) for the two cell-vertices (nodes) it join.

Methods

Creation methods

The first step is to populate the data structure with the topological data from the segmented tissue. Then we can attach spatial properties to the topological elements.

Add topological elements

The following methods allow adding topological elements to the tissue graph:

tg = TissueGraph()
tg.add_cells(cells)
tg.add_cell_walls(walls)
tg.add_cell_vertices(vertices)
tg.add_cell_edges(edges)
Examples
tg.add_cells([2, 3, 4])  # add cell ids to the graph
tg.add_cell_walls([(2, 3), (2, 4)])  # add two edges to the graph

Add properties

The following methods allow adding named properties (and their unit) to topological elements to the tissue graph:

tg.add_cell_property(name, values, unit)
tg.add_cell_wall_property(name, values, unit)
tg.add_cell_edge_property(name, values, unit)
tg.add_cell_vertex_property(name, values, unit)

The values should be dictionaries with keys matching the type of element ids they correspond to.

Examples
tg.add_cell_property('volume', {2: 25.6, 3: 31.2}, 'µm³')  # add a 'volume' property to the cells
tg.add_cell_wall_property('area', {(2, 3): 15.6}, 'µm²')  # add an 'area' property to the cell walls

Inspection methods

Two options are possible to access properties:

  1. get the property value for a single element id, in that case we will return an integer|float|numpy.array (e.g. the cell’s neighborhood size, volume, inertia axes) or a list of integers|floats|numpy.arrays (e.g. the cell’s neighbors).

  2. get the property values for a list of element ids (all of them or according to a specific list), in that case we will return a dictionary of values for all elements (or those selected).

Important

In both cases, if a property is not defined for an element, None will be used as default value (default missing value should be editable)

List of ids

The following methods return list of ids:

tg.cell_ids()
tg.cell_wall_ids()
tg.cell_edge_ids()
tg.cell_vertex_ids()

List of properties

The following methods return dictionary of properties and their units by elements’ type:

tg.list_cell_properties()
tg.list_wall_properties()
tg.list_cell_edge_properties()
tg.list_cell_vertex_properties()

Example for a graph with cell’s volumes:

>>> tg.cell_properties()
{'volume': 'µm³'}

Single element - single property

To access the properties of a single element, the following methods:

tg.cell_property(cell_id, name, default=None)
tg.cell_wall_property(wall_id, name, default=None)

This return a single value which type depends on the property type (integer, float, numpy.array).

Important

If the property is unknown to the cell_id, return a default value.

Single element - all properties

tg.cell_properties(cell_id, ppties=None, default=None)
tg.cell_wall_properties(wall_id, ppties=None, default=None)

This return a dictionary with property names as keys and their associated value, if defined, which type depends on the property type (integer, float, numpy.array).

Warning

If names is None, what should we return?

  1. all known property to the element (skip those undefined for the element)

  2. all known property to the graph for the element (with default value)

Single property - several elements

tg.cell_property_dict(names, cell_ids=None, default=None)
tg.cell_wall_property_dict(names, wall_ids=None, default=None)

This return a dictionary with element ids as keys and their associated value, if defined, which type depends on the property type (integer, float, numpy.array).

Important

If cell_ids is None, returns the dictionary for all cells known to the graph, with a default value for cells without a property value.

Exceptions

As node neighbors are quite useful to explore the graph, there are a few dedicated method:

tg.cell_neighbors(cell_id)
tg.cell_vertex_neighbors(cell_vertex_id)
tg.cell_neighbors_dict()

Bulk export to CSV

It can be useful to export all (or a selection of) properties known to a CSV file to process or display them in an external app.

tg.cell_csv(names=None, cell_ids=None, default=None)
tg.cell_wall_csv(names=None, wall_ids=None, default=None)

Important

If names is None, returns all known property to the graph for this element, with default for element without a property value.

Important

If cell_ids is None, returns the dictionary for all cells known to the graph, with a default value for cells without a property value.

Spatial differentiation functions

Laplacian

Formulae

The Laplacian for cell \(i\), on a given property, can be expressed as: \(\text{L}_i = \dfrac{1}{N} . \sum_{x=1}^N (v_i - v_x)\), with \(v_x\) the property values of the \(N\) neighbors of cell \(i\) and \(v_i\) its property value.

Mean absolute deviation

Creation

Can be created from list of cells, & cell walls

tissue = TissueImage3D(img, background=1, not_a_label=0)
tg = TissueGraph()
tg.add_cells(tissue.cell_ids())  # add the list of cells
tg.cell_ids()[:10]  # access the first 10