R/count_touching_cells.R
count_touching_cells.Rdcount_touching_cells uses morphological analysis of nuclear and
membrane segmentation maps to find touching cells of paired phenotypes.
It reports the number of touching cells found and, optionally,
writes image files showing the touching cells.
count_touching_cells(
cell_seg_path,
pairs,
colors = NULL,
phenotype_rules = NULL,
categories = NULL,
write_images = !is.null(colors),
output_base = NULL
)The path to the cell seg data file. The same directory
must also contain _memb_seg_map.tif or _binary_seg_maps.tif and, if
write_images is true, a TIFF or JPEG composite image from inForm.
A list of pairs of phenotypes. Each entry is a two-element vector. The result will contain one line for each pair showing the number of cells and number of touches. Pairs must match two different sets of cells; in particular, touches of a phenotype to itself are not supported.
A named list of phenotype colors to use when drawing
the output. Only used when write_images is TRUE.
(Optional) A named list.
Item names are phenotype names and must match entries in pairs.
Item values are selectors for select_rows.
If given, a vector or list of tissue category names. Categories not in the list will be excluded from the analysis.
If TRUE, for each pair, write an image showing the
touching pairs. Requires colors and a composite image in the same
directory as the cell seg table.
Base path for image output.
If NULL, output will be to the same
directory as the cell table.
Returns a tibble with one row for each pair in
pairs, containing these columns:
slide_idSlide ID from the data file, if available.
sourceBase file name of the source file with
_cell_seg_data.txt stripped off for brevity.
phenotype1The name of the first phenotype in the touching pair.
phenotype2The name of the second phenotype in the touching pair.
total1The total number of phenotype1 cells
in the image.
total2The total number of phenotype2 cells
in the image.
p1_touch_p2The number of phenotype1 cells
touching a phenotype2 cell.
p2_touch_p1The number of phenotype2 cells
touching a phenotype1 cell.
touch_mutualThe number of mutually touching pairs.
This function requires a cell seg data file and a matching
segmentation map file. If write_images is true,
a composite image is required.
If the cell seg data uses micron units, a composite data file is also
required.
Cells are considered to touch if they have any amount of common membrane as determined by the inForm membrane segmentation. Cells which meet only at a corner, like black squares on a checkerboard, are not counted as touching.
The number of touching cells is reported in three ways. For a pair of phenotypes A and B, this function reports the number of A touching a B, the number of B touching an A, and the number of mutually touching pairs. Note that the number of mutual touches is often larger than the count of either "A touching B" or "B touching A" because a single touching cell may be part of multiple pairs.
The image files written show cells of the selected phenotypes on a background of the composite. Touching cells are filled in the provided color; cells which are not touching the other phenotype are outlined. Image files are written as TIFF files to preserve the fine detail of cell boundaries.
Images are only written when both phenotypes of the pair are represented.
See the tutorial
Selecting cells within a cell segmentation table
for more on
the use of pairs and phenotype_rules.
Other distance functions:
compute_all_nearest_distance(),
count_within_batch(),
count_within_many(),
count_within(),
distance_matrix(),
find_nearest_distance(),
spatial_distribution_report(),
subset_distance_matrix()
if (FALSE) {
# This example creates an image in a subdirectory of the
# current user's directory.
cell_seg_path <- sample_cell_seg_path()
pairs <- list(c("CD68+", "CD8+"))
colors <- c("CD68+"='magenta', "CD8+"='yellow')
output_base <- path.expand('~/touches')
count_touching_cells(cell_seg_path, pairs, colors,
output_base=output_base)
# This example will count and image all files in the `base_path` directory.
base_path <- '/path/to/data'
output_base <- file.path(base_path, 'touches')
files <- list_cell_seg_files(base_path)
# The phenotype pairs to locate. This will find CD8 cells touching
# tumor cells, and, separately, CD8 cells touching CD68 cells.
pairs <- list(c("CD8+", "CK+"),
c("CD8+", "CD68+"))
# Colors for all the phenotypes mentioned in pairs
colors <- list(
'CD8+' = 'yellow',
'CK+' = 'cyan',
'CD68+' = 'magenta'
)
# Count and visualize touching cells
touch_counts <- purrr::map_df(files, function(path) {
cat('Processing', path, '\n')
count_touching_cells(path, pairs, colors, output_base=output_base)
})
# Save the result
touches_path <- file.path(output_base, 'TouchCounts.csv')
readr::write_csv(touch_counts, touches_path)
# The phenotype definitions can be more complex. The default is to use
# the names in `pairs`. Using `phenotype_rules`, the definition can be
# anything allowed by select_rows().
# You can also limit the tissue category.
# For example, find all touches between lymphocytes and tumor cells
# within the tumor:
pairs <- list(c('Tumor', 'Lymphocyte'))
colors <- list(Tumor='cyan', Lymphocyte='yellow')
phenotype_rules <- list(
Lymphocyte=c('CD8+', 'FoxP3+')
)
touch_counts <- map_df(files, function(path) {
cat('Processing', path, '\n')
count_touching_cells(path, pairs, colors, phenotype_rules,
categories='tumor',
output_base=output_base)
})
# Then write the results as above.
}