Infection-associated niche identification
Source:vignettes/05_Infection-associated_niche_identification.Rmd
05_Infection-associated_niche_identification.RmdOverview
This vignette describes how to identify infection-associated niches
using STID after preprocessing, background correction when
required, and infection-associated spot detection.
STID supports three complementary niche identification
modes according to the spatial organization of positive spots:
- Foci-type niches, which represent highly localized infection-associated regions;
- Aggregated-type niches, which represent spatially clustered positive regions with broader regional structure;
- Dispersed-type niches, which represent spatially distributed positive spots without strong regional aggregation.
This vignette covers:
- identifying foci-type niches using lasso-based spatial boundary detection;
- identifying aggregated-type niches using regional spatial transcriptomic signal aggregation;
- identifying dispersed-type niches at the positive-spot level;
- visualizing niche boundaries and distance-dependent signal profiles.

Overview of the three infection-associated niche identification strategies.
Note: Update the input object names, niche-identification parameters according to the dataset used in your analysis.
Reference code: For more runnable code examples, please refer to the article code.
Example data
The foci-type example uses the AE STID_obj_after object
generated in infection-associated spot detection workflow, and the
analysis focuses on the DPI_4_2 (PI4d) sample.
The aggregated-type uses the JE STID_obj object
generated in infection-associated spot detection workflow, and the
analysis focuses on the D5_1 (PI5d) sample.
The dispersed-type uses the JE STID_obj object generated
in infection-associated spot detection workflow, and the analysis
focuses on the D3_1 (PI3d) sample.
Foci-type niche identification
For foci-type niches, clear infectious foci were first confirmed in
H&E images. NicheDetect_Lasso was then used to
delineate foci-associated niches by integrating infected spots,
host-responsive spots, cell-type annotations, and H&E histology.
Foci-type niche identification is designed for highly localized infection-associated regions.
Note: Replace
STID_obj_after,DPI_4_2,anno,batch, color vectors, marker genes, gene-set names, and metadata keys with the corresponding values from your dataset.
foci_celltype_colors <- c(
"HsPCs" = "#E41A1C",
"Hepatocytes" = "grey95",
"Infla Heps" = "#4DAF4A",
"Fibroblasts" = "#984EA3",
"Cho/Spp1+ cells" = "#FFFF33",
"Spp1+ MoMFs" = "#FF7F00",
"MoKCs" = "#377EB8",
"Neutrophils" = "#F781BF",
"B/plasma cells" = "#A65628",
"Others" = "#8DA0CB"
)
STID_obj_lasso <- NicheDetect_Lasso(
STID_obj = STID_obj_after,
meta_key = "coord",
group_by = "anno",
col = foci_celltype_colors,
grp_nm = "AE_lasso"
)
print(STID_obj_lasso)
foci_lasso_key <- "M2_NicheDetect_Lasso_AE_lasso"
lasso_meta <- GetMetaData(
STID_obj_lasso,
meta_key = foci_lasso_key,
add_coord = FALSE
)[[1]]Foci-type niche boundary detected using lasso-based spatial delineation.
Visualize foci-type niche regions
After niche identification, boundary spots were defined using kNN-based neighborhood relationships, and each ROI center was estimated from median spot coordinates. Distances to the nearest center were then calculated, and bystander spots were assigned to the closest ROI.
The following plots show the spatial distribution of lasso-defined regions of interest and the corresponding region labels.
FOCI_DARK <- c("#F81B02FF", "#FC7715FF", "#FCB11C")
FOCI_LIGHT <- c("#F88A7E", "#FCC093", "#FCDB9A")
# ROI
Plot_Spatial(
plot_data = lasso_meta,
x_colnm = "x",
y_colnm = "y",
group_by = "ROI_region",
facet_grpnm = "batch",
datatype = "discrete",
col = list(dis = c("grey95", "#FFC4E1", "#244D7F", "#EB1E2C"), con = NULL),
pt_size = 1,
vmin = NULL,
vmax = "p99",
title = NULL,
subtitle = NULL,
black_bg = FALSE
)
# Region
Plot_Spatial(
plot_data = lasso_meta,
x_colnm = "x",
y_colnm = "y",
group_by = "All_ROI_label2",
facet_grpnm = "batch",
datatype = "discrete",
col = list(dis = c(FOCI_LIGHT, FOCI_DARK), con = NULL),
pt_size = 1.1,
vmin = NULL,
vmax = "p99",
title = NULL,
subtitle = NULL,
black_bg = FALSE
)Expand foci-type niche boundaries
NicheExpand can refine initial niches by adding
bystander spots within a selected distance from each ROI boundary.
Niche expansion can be used to include spatial neighborhoods surrounding the detected foci. The expansion distance should be selected according to platform resolution, bin size, and the expected physical scale of infection-associated regions.
STID_obj_expand <- NicheExpand(
STID_obj = STID_obj_lasso,
meta_key = foci_lasso_key,
pos_colnm = "ROI_label",
center_colnm = "ROI_center",
expand_dist = 8,
grp_nm = "AE_expand"
)
print(STID_obj_expand)
foci_expand_key <- "M2_NicheExpand_AE_expand"
expand_meta <- GetMetaData(
STID_obj_expand,
meta_key = foci_expand_key,
add_coord = TRUE
)[[1]]Note: Update
expand_distaccording to the bin size and the expected spatial radius of the niche boundary in your dataset.
# ROI
Plot_Spatial(
plot_data = expand_meta,
x_colnm = "x",
y_colnm = "y",
group_by = "ROI_region",
facet_grpnm = "batch",
datatype = "discrete",
col = list(dis = c("grey95", "#FFC4E1", "#244D7F", "#EB1E2C"), con = NULL),
pt_size = 1,
vmin = NULL,
vmax = "p99",
title = NULL,
subtitle = NULL,
black_bg = FALSE
)
# Region
Plot_Spatial(
plot_data = expand_meta,
x_colnm = "x",
y_colnm = "y",
group_by = "All_ROI_label2",
facet_grpnm = "batch",
datatype = "discrete",
col = list(dis = c(FOCI_LIGHT, FOCI_DARK), con = NULL),
pt_size = 1.1,
vmin = NULL,
vmax = "p99",
title = NULL,
subtitle = NULL,
black_bg = FALSE
)
Expanded foci-type niche regions.
Plot distance-dependent signal profiles
STID summarizes distance-dependent gradients from niche centers to surrounding tissue. Gene-expression profiles are smoothed with GAMs, while cell-composition profiles are calculated in distance bins; both outputs can be visualized with niche boundaries annotated.
Distance profiles summarize how pathogen-derived genes, host-responsive genes, or gene-set scores change from the niche center toward the surrounding tissue.
foci_gene_detection_key <- "M1_SpotDetect_Gene_AE_correct_after_host_gene_white"
foci_pcd_detection_key <- "M1_SpotDetect_Geneset_AE_correct_after_PCD_white"
foci_parasite_geneset_key <- "M1_SpotDetect_Geneset_AE_correct_after_KEGG_Parasite_white"
# Profiles before niche expansion.
Plot_DistLine_Exp(
STID_obj = STID_obj_lasso,
features = c("EmuJ-002209100", "Spp1", "Il1b"),
feature_colnm = "all_gene_nFeature(sum)",
col = c("#F81B02FF", "#3B95C4FF", "#3B95C4FF", "#F81B02FF"),
facet_grpnm = "batch",
meta_key = list(c(foci_gene_detection_key, foci_lasso_key))
)
Plot_DistLine_Exp(
STID_obj = STID_obj_lasso,
features = NULL,
feature_colnm = c("Necroptosis"),
col = c("#3B95C4FF"),
facet_grpnm = "batch",
meta_key = list(c(foci_pcd_detection_key, foci_lasso_key))
)
Plot_DistLine_Exp(
STID_obj = STID_obj_lasso,
features = NULL,
feature_colnm = c("Malaria"),
col = c("#3B95C4FF"),
facet_grpnm = "batch",
meta_key = list(c(foci_parasite_geneset_key, foci_lasso_key))
)
# Profiles after niche expansion.
Plot_DistLine_Exp(
STID_obj = STID_obj_expand,
features = c("EmuJ-002209100", "Spp1", "Il1b"),
feature_colnm = "all_gene_nFeature(sum)",
col = c("#F81B02FF", "#3B95C4FF", "#3B95C4FF", "#F81B02FF"),
facet_grpnm = "batch",
meta_key = list(c(foci_gene_detection_key, foci_expand_key))
)
Plot_DistLine_Exp(
STID_obj = STID_obj_expand,
features = NULL,
feature_colnm = c("Necroptosis"),
col = c("#3B95C4FF"),
facet_grpnm = "batch",
meta_key = list(c(foci_pcd_detection_key, foci_expand_key))
)
Plot_DistLine_Exp(
STID_obj = STID_obj_expand,
features = NULL,
feature_colnm = c("Malaria"),
col = c("#3B95C4FF"),
facet_grpnm = "batch",
meta_key = list(c(foci_parasite_geneset_key, foci_expand_key))
)
Distance-dependent feature profiles for foci-type niches.
Note: Replace the marker genes, gene-set names, metadata keys, and
facet_grpnmwith values that correspond to the features and sample metadata in your dataset.
Aggregated-type niche identification
For aggregated-type niches, NicheDetect_STS
automatically identifies clustered positive regions after low-density
filtering and kNN-based refinement of positive spots. Region-level mode
uses DBSCAN and hull reconstruction to define niche regions, whereas
spot-level mode uses kNN graphs and connected components to delineate
contiguous positive-spot clusters.
Aggregated-type niche identification detects spatially clustered
regions based on pathogen-infected or host-responsive positive spots. In
the JEV example, the D5_1 (PI5d) sample is used to
illustrate aggregated spatial organization.
Note: Replace detection metadata keys, positive-label columns,
density_thres,region_detect_method, and output group names according to the spatial aggregation pattern and detection results in your dataset.
# pathogen-infected niche
STID_obj_aggregated <- NicheDetect_STS(
STID_obj = STID_obj,
meta_key = "M1_SpotDetect_Gene_JEV_multisamp_microbe_gene",
spatial_scale_method = "region",
region_detect_method = "convex",
update_spots = FALSE,
ROI_size = NULL,
density_thres = 1,
pos_colnm = "Label_all_gene_nFeature(sum)",
description = NULL,
grp_nm = "STS_JEV_multisamp_microbe_region",
dir_nm = "M2_NicheDetect_STS"
)
pathogen_niche_key <- "M2_NicheDetect_STS_STS_JEV_multisamp_microbe_region"
pathogen_meta <- GetMetaData(
STID_obj_aggregated,
meta_key = pathogen_niche_key,
add_coord = FALSE
)[[1]]
# host-responsive niche
STID_obj_aggregated <- NicheDetect_STS(
STID_obj = STID_obj_aggregated,
meta_key = "M1_SpotDetect_Gene_JEV_multisamp_GO_viral_white",
spatial_scale_method = "region",
region_detect_method = "convex",
update_spots = TRUE,
ROI_size = NULL,
density_thres = 0.3,
pos_colnm = "Label_RESPONSE_TO_VIRUS",
description = NULL,
grp_nm = "STS_JEV_multisamp_host_region",
dir_nm = "M2_NicheDetect_STS"
)
print(STID_obj_aggregated)
host_niche_key <- "M2_NicheDetect_STS_STS_JEV_multisamp_host_region"
host_meta <- GetMetaData(
STID_obj_aggregated,
meta_key = host_niche_key,
add_coord = FALSE
)[[1]]The density_thres parameter should be calibrated to the
expected compactness of pathogen-positive or host-responsive positive
regions.
Visualize aggregated niches
The following plots show the spatial distributions of pathogen-infected and host-responsive aggregated niches.
PATHOGEN_DARK <- c("#50C49FFF", "#FC7715FF", "#FCB11C", "#F81B02FF", "#3B95C4FF", "#B560D4FF")
PATHOGEN_LIGHT <- c("#BBBFA1", "#FCC093", "#FCDB9A", "#F88A7E", "#9DB7C4", "#D1CAD4")
HOST_DARK <- c("#F81B02FF", "#FC7715FF", "#FCB11C", "#B560D4FF")
HOST_LIGHT <- c("#F88A7E", "#FCC093", "#FCDB9A", "#D1CAD4")
# Pathogen: ROI
Plot_Spatial(
plot_data = pathogen_meta,
x_colnm = "x",
y_colnm = "y",
group_by = "ROI_region",
facet_grpnm = "new_samp",
datatype = "discrete",
col = list(dis = c("grey95", "#FFC4E1", "#244D7F", "#EB1E2C"), con = NULL),
pt_size = 1,
vmin = NULL,
vmax = "p99",
title = NULL,
subtitle = NULL,
black_bg = FALSE
)
# Pathogen: Region
Plot_Spatial(
plot_data = pathogen_meta,
x_colnm = "x",
y_colnm = "y",
group_by = "All_ROI_label2",
facet_grpnm = "new_samp",
datatype = "discrete",
col = list(dis = c(PATHOGEN_LIGHT, PATHOGEN_DARK), con = NULL),
pt_size = 1.1,
vmin = NULL,
vmax = "p99",
title = NULL,
subtitle = NULL,
black_bg = FALSE
)
# Host: ROI
Plot_Spatial(
plot_data = host_meta,
x_colnm = "x",
y_colnm = "y",
group_by = "ROI_region",
facet_grpnm = "new_samp",
datatype = "discrete",
col = list(dis = c("grey95", "#FFC4E1", "#244D7F", "#EB1E2C"), con = NULL),
pt_size = 1,
vmin = NULL,
vmax = "p99",
title = NULL,
subtitle = NULL,
black_bg = FALSE
)
# Host: Region
Plot_Spatial(
plot_data = host_meta,
x_colnm = "x",
y_colnm = "y",
group_by = "All_ROI_label2",
facet_grpnm = "new_samp",
datatype = "discrete",
col = list(dis = c(HOST_LIGHT, HOST_DARK), con = NULL),
pt_size = 1.1,
vmin = NULL,
vmax = "p99",
title = NULL,
subtitle = NULL,
black_bg = FALSE
)
Spatial distribution of pathogen-infected and host-responsive aggregated niches.
Plot distance-dependent signal profiles
Distance profiles can be used to compare molecular signal gradients from the center of aggregated niches toward surrounding tissue.
# Profiles for pathogen-infected niche.
Plot_DistLine_Exp(
STID_obj = STID_obj_aggregated,
features = c("NS5", "Ccl2"),
feature_colnm = "all_gene_nFeature(sum)",
loop_id = "D5_1",
col = c("#F81B02FF", "#3B95C4FF", "#F81B02FF"),
facet_grpnm = "grp",
meta_key = list(c("M1_SpotDetect_Gene_JEV_multisamp_microbe_gene", pathogen_niche_key))
)
Plot_DistLine_Exp(
STID_obj = STID_obj_aggregated,
features = NULL,
feature_colnm = c("RESPONSE_TO_VIRUS"),
loop_id = "D5_1",
col = "#3B95C4FF",
facet_grpnm = "grp",
meta_key = list(c("M1_SpotDetect_Gene_JEV_multisamp_GO_viral_white", pathogen_niche_key))
)
Plot_DistLine_Exp(
STID_obj = STID_obj_aggregated,
features = NULL,
feature_colnm = c("Necroptosis"),
loop_id = "D5_1",
col = "#3B95C4FF",
facet_grpnm = "grp",
meta_key = list(c("M1_SpotDetect_Geneset_JEV_correct_before_PCD_white", pathogen_niche_key))
)
# Profiles for host-responsive niche.
Plot_DistLine_Exp(
STID_obj = STID_obj_aggregated,
features = c("NS5", "Ccl2"),
feature_colnm = "all_gene_nFeature(sum)",
loop_id = "D5_1",
col = c("#F81B02FF", "#3B95C4FF", "#F81B02FF"),
facet_grpnm = "grp",
meta_key = list(c("M1_SpotDetect_Gene_JEV_multisamp_microbe_gene", host_niche_key))
)
Plot_DistLine_Exp(
STID_obj = STID_obj_aggregated,
features = NULL,
feature_colnm = c("RESPONSE_TO_VIRUS"),
loop_id = "D5_1",
col = "#3B95C4FF",
facet_grpnm = "grp",
meta_key = list(c("M1_SpotDetect_Gene_JEV_multisamp_GO_viral_white", host_niche_key))
)
Plot_DistLine_Exp(
STID_obj = STID_obj_aggregated,
features = NULL,
feature_colnm = c("Necroptosis"),
loop_id = "D5_1",
col = "#3B95C4FF",
facet_grpnm = "grp",
meta_key = list(c("M1_SpotDetect_Geneset_JEV_correct_before_PCD_white", host_niche_key))
)
Distance-dependent feature profiles for aggregated niches.
Compare pathogen-infected and host-responsive niches
CompareNiche() quantifies the spatial relationship
between two niche definitions, such as pathogen-infected niches and
host-responsive niches.
CompareNiche(
STID_obj = STID_obj_aggregated,
meta_key1 = pathogen_niche_key,
meta_key2 = host_niche_key,
bins = 15
)The following plot shows the spatial overlap between pathogen-infected and host-responsive aggregated niches, as well as the distance distribution of host-responsive niche spots to the nearest pathogen-infected niche center.

Spatial comparison between pathogen-infected and host-responsive aggregated niches.
Dispersed-type niche identification
For dispersed-type niches, NicheDetect_Spot treats each
positive spot as an independent niche.
Dispersed-type niche identification is designed for
infection-associated signals that are spatially distributed rather than
concentrated in continuous regions. In the JEV example, the
PI3d sample is used to illustrate dispersed positive-spot
organization.
Note: Replace positive-label columns, metadata keys, and output group names according to the dispersed infection-associated spots in your dataset.
STID_obj_dispersed <- NicheDetect_Spot(
STID_obj = STID_obj,
pos_colnm = "Label_all_gene_nFeature(sum)",
meta_key = "M1_SpotDetect_Gene_JEV_multisamp_microbe_gene",
description = NULL,
grp_nm = "D3_1"
)
print(STID_obj_dispersed)
dispersed_niche_key <- "M2_NicheDetect_Spot_D3_1"
Plot_DistLine_Exp(
STID_obj = STID_obj_dispersed,
features = c("NS5", "Ccl2"),
feature_colnm = "all_gene_nFeature(sum)",
loop_id = "D3_1",
col = c("#F81B02FF", "#3B95C4FF", "#F81B02FF"),
distance_scale = FALSE,
exp_scale = FALSE,
facet_grpnm = "grp",
meta_key = list(c("M1_SpotDetect_Gene_JEV_multisamp_microbe_gene", dispersed_niche_key))
)
Plot_DistLine_Exp(
STID_obj = STID_obj_dispersed,
features = NULL,
feature_colnm = c("RESPONSE_TO_VIRUS"),
loop_id = "D3_1",
col = "#3B95C4FF",
distance_scale = FALSE,
exp_scale = FALSE,
facet_grpnm = "grp",
meta_key = list(c("M1_SpotDetect_Gene_JEV_multisamp_GO_viral_white", dispersed_niche_key))
)
Plot_DistLine_Exp(
STID_obj = STID_obj_dispersed,
features = NULL,
feature_colnm = c("Necroptosis"),
loop_id = "D3_1",
col = "#3B95C4FF",
distance_scale = FALSE,
exp_scale = FALSE,
facet_grpnm = "grp",
meta_key = list(c("M1_SpotDetect_Geneset_JEV_correct_before_PCD_white", dispersed_niche_key))
)
Distance-dependent feature profiles for dispersed-type niches.
Notes
- Confirm that infection-associated positive spots have been generated before running niche identification.
- Select the niche identification mode according to the observed spatial organization of positive spots.
- Use foci-type detection for compact spatial regions, aggregated-type detection for broader clustered regions, and dispersed-type detection for non-contiguous positive spots.
- Calibrate
density_thres,expand_dist,ROI_size, and thresholding parameters according to platform resolution, bin size, tissue structure, and expected infection burden. - Verify all metadata keys generated by spot detection and niche identification before plotting or comparing niches.
Next steps
This vignette identified infection-associated niches and, when needed, expanded niche boundaries for downstream spatial-gradient analysis. In the next vignette, we will use these niche labels to construct single-sample niche objects and characterize their spatial organization, cellular composition, molecular features, cell–cell communication, gene regulatory networks, and host–pathogen interactions.
Session information
sessionInfo()
#> R version 4.2.0 (2022-04-22 ucrt)
#> Platform: x86_64-w64-mingw32/x64 (64-bit)
#> Running under: Windows 10 x64 (build 22000)
#>
#> Matrix products: default
#>
#> locale:
#> [1] LC_COLLATE=Chinese (Simplified)_China.utf8
#> [2] LC_CTYPE=Chinese (Simplified)_China.utf8
#> [3] LC_MONETARY=Chinese (Simplified)_China.utf8
#> [4] LC_NUMERIC=C
#> [5] LC_TIME=Chinese (Simplified)_China.utf8
#>
#> attached base packages:
#> [1] stats graphics grDevices utils datasets methods base
#>
#> loaded via a namespace (and not attached):
#> [1] digest_0.6.35 R6_2.6.1 jsonlite_1.8.8 lifecycle_1.0.5
#> [5] evaluate_1.0.1 cachem_1.1.0 rlang_1.1.7 cli_3.6.5
#> [9] rstudioapi_0.15.0 fs_1.6.3 jquerylib_0.1.4 bslib_0.8.0
#> [13] ragg_1.3.0 rmarkdown_2.29 pkgdown_2.2.0 textshaping_0.3.6
#> [17] desc_1.4.3 tools_4.2.0 htmlwidgets_1.6.4 yaml_2.3.10
#> [21] xfun_0.49 fastmap_1.2.0 compiler_4.2.0 systemfonts_1.0.4
#> [25] htmltools_0.5.8.1 knitr_1.49 sass_0.4.9