# load packages
library(tidyverse) # for data manipulation and visualization
library(RColorBrewer) # for color palettes
library(patchwork) # for combining plots
library(pracma) # for calculating the area of a polygon
library(terra) # for raster manipulation
library(grid) # for working with grid graphics3 ggplot2“银河系”等高线&HE
ggplot2版本的“银河系”,并将等高线展示在H&E图上
在2025-07-29,我们展示过H&E起源版本的“银河系”(QuPath:“银河系”起源于H&E)。在2025-08-12,我们通过R的ggplot2来展示该“银河系”(R:ggplot2等高线图版本的“银河系”)。在2025-08-15,我们进一步计算特定等高线的面积(R:ggplot2版本的“银河系”,并计算特定等高线的面积)。
这次,我们进一步将等高线和特定等高线的面积展示在H&E图上。
1. Load packages and read data/加载包和读取数据
加载包。
读取数据。
# read the table
txt_file <- "raw_data/2025-08-12_QuPath_InstanSeg.txt" # specify the path to the text file
df <- txt_file |> read_delim(delim = "\t", col_names = TRUE, show_col_types = FALSE) # read the text file as a data frame
txt_file |> rm() # remove the txt_file variable to free up memory
df <- df |>
dplyr::select(`Centroid X µm`, `Centroid Y µm`) # select the columns specifying the coordinates of nuclei
df |> head() # display the first few rows of the data frame# A tibble: 6 × 2
`Centroid X µm` `Centroid Y µm`
<dbl> <dbl>
1 131. 88.4
2 118. 90.2
3 169. 90.9
4 179. 95.0
5 230. 96.5
6 119. 96.8
2. Plot the nuclei as points and add contour lines/绘制细胞核和添加等高线
Plot the nuclei as points and add contour lines./绘制细胞核和等高线。
nuclei_contour_plot <- ggplot(df, aes(x = `Centroid X µm`, y = `Centroid Y µm`)) +
geom_point(color = "#0072B2") + # scatter plot
geom_density_2d(aes(color = after_stat(level)), bins = 15) + # add contour lines
scale_color_viridis_c(option = "H") + # set color scale for contour lines
scale_x_continuous(limits = c(0, 1000)) + # set x limits
scale_y_continuous(limits = c(0, 900)) + # set y limits
theme_classic() # apply classic theme
nuclei_contour_plot
3. Claculate the area of a contour level/计算一个等高线的面积
Extract the data used to create the contour plot and display its distinct levels./提取用于创建等高线图的数据并显示它的不同等级。
plot_data <- nuclei_contour_plot |>
ggplot_build() |>
pluck("data", 2) # extract the data used to create the contour plot
plot_data |> dim() # display the dimensions of the contour plot data[1] 3915 12
plot_data |> distinct(level) # display distinct levels in the contour plot level
1 2.666667e-07
2 5.333333e-07
3 8.000000e-07
4 1.066667e-06
5 1.333333e-06
6 1.600000e-06
7 1.866667e-06
8 2.133333e-06
9 2.400000e-06
10 2.666667e-06
11 2.933333e-06
12 3.200000e-06
13 3.466667e-06
14 3.733333e-06
Select a level (e.g. 9th level)./选择一个等高线(比如第9个level)
levels <- plot_data |> distinct(level) # select the unique levels
plot_data_9 <- plot_data |>
filter(level == levels$level[9]) # filter the data for the 8th levelPlot the 9th contour level./绘制第9个等高线。
ggplot(plot_data_9, aes(x = x, y = y, group = group)) +
geom_polygon(color = "blue", fill = "lightblue", alpha = 0.5) + # draw the polygon with specified fill and border color
theme_classic() + # apply classic theme
scale_x_continuous(limits = c(0, 1000)) + # set x limits
scale_y_continuous(limits = c(0, 900)) # set y limits
Calculate the area and center of the 9th contour level using the pracma package./计算第9个等高线的面积和中心坐标。
# set a function to calculate the area of a polygon
calculate_polygon_area_pracma <- function(df) {
x <- df$x
y <- df$y
n <- length(x)
area <- polyarea(x, y)
center <- poly_center(x, y)
return(c(area, center))
}
# use the function to calculate the area and center position of each polygon of 9th contour level
area_each_polygon <- plot_data_9 |>
group_by(group) |>
group_map(~ calculate_polygon_area_pracma(.x))
area_each_polygon[[1]]
[1] 47900.0729 239.5070 544.1073
[[2]]
[1] 17762.3143 730.3807 461.9802
[[3]]
[1] 17132.1260 742.2732 276.3749
Plot the area of the 9th contour level.
ggplot(plot_data_9, aes(x = x, y = y, group = group)) +
geom_polygon(color = "blue", fill = "lightblue", alpha = 0.5) + # draw the polygon with specified fill and border color
theme_classic() + # apply classic theme
scale_x_continuous(limits = c(0, 1000)) + # set x limits
scale_y_continuous(limits = c(0, 900)) + # set y limits
annotate("text", x = area_each_polygon[[1]][2], y = area_each_polygon[[1]][3], label = round(area_each_polygon[[1]][1], 2), size = 5, color = "red") + # add the area and center label
annotate("text", x = area_each_polygon[[2]][2], y = area_each_polygon[[2]][3], label = round(area_each_polygon[[2]][1], 2), size = 5, color = "red") + # add the area and center label
annotate("text", x = area_each_polygon[[3]][2], y = area_each_polygon[[3]][3], label = round(area_each_polygon[[3]][1], 2), size = 5, color = "red") # add the area and center label
4. Read the original H&E/读取原始H&E图片
img_path <- "images/he_normal.tif"
img <- terra::rast(img_path) # read the TIFF imageWarning: [rast] unknown extent
img_path |> rm() # remove the img_path variable to free up memory
img |> dim() # display the dimensions: height x width x channels[1] 1536 1792 3
img <- as.array(img)/255 # normalize the image (the original tif is 8-bit, so we need to divide by 255 to get the values between 0 and 1)
img_grob <- grid::rasterGrob(img, interpolate = TRUE) # convert raster image to graphical object for ggplot5. Plot contour level、and area of 9th contour level on the H&E image/在H&E图上绘制等高线和9th等高线的面积
ggplot(df, aes(x = `Centroid X µm`, y = `Centroid Y µm`)) +
annotation_custom(
img_grob, xmin = 0, xmax = 896, ymin = 0, ymax = 768
) + # Since the pixel width was set to 0.5 um, so the size of the image changed to 896 um x 768 um.
geom_polygon(data = plot_data_9, aes(x = x, y = y, group = group), fill = "lightblue", alpha = 0.8) +
geom_point(color = "#969696") + # scatter plot
geom_density_2d(bins = 15, color = "#cbc9e2") + # add contour lines
scale_x_continuous(limits = c(0, 1000)) + # set x limits
scale_y_continuous(limits = c(0, 900)) + # set y limits
theme_classic() + # apply classic theme
coord_fixed() + # fix the aspect ratio
annotate("text", x = area_each_polygon[[1]][2], y = area_each_polygon[[1]][3], label = round(area_each_polygon[[1]][1], 2), size = 6, color = "#f03b20") + # add the area and center label
annotate("text", x = area_each_polygon[[2]][2], y = area_each_polygon[[2]][3], label = round(area_each_polygon[[2]][1], 2), size = 6, color = "#f03b20") + # add the area and center label
annotate("text", x = area_each_polygon[[3]][2], y = area_each_polygon[[3]][3], label = round(area_each_polygon[[3]][1], 2), size = 6, color = "#f03b20") # add the area and center label
6. “银行系”的起源
