├── .Rbuildignore ├── .github ├── .gitignore └── workflows │ └── pkgdown.yaml ├── .gitignore ├── DESCRIPTION ├── LICENSE ├── NAMESPACE ├── NEWS.md ├── R ├── AUC_of_cross_function.R ├── R_BC.R ├── SPIAT-package.R ├── SPIAT.R ├── average_marker_intensity_within_radius.R ├── average_minimum_distance.R ├── average_nearest_neighbor_index.R ├── average_percentage_of_cells_within_radius.R ├── calculate_cell_proportions.R ├── calculate_cross_functions.R ├── calculate_distance_to_tumour_margin.R ├── calculate_entropy.R ├── calculate_minimum_distances_between_celltypes.R ├── calculate_pairwise_distances_between_celltypes.R ├── calculate_percentage_of_grids.R ├── calculate_proportions_of_cells_in_structure.R ├── calculate_spatial_autocorrelation.R ├── calculate_summary_distances_between_celltypes.R ├── calculate_summary_distances_of_cells_to_borders.R ├── composition_of_neighborhoods.R ├── compute_gradient.R ├── crossing_of_crossK.R ├── define_celltypes.R ├── define_structure.R ├── defined_image.R ├── dimensionality_reduction_plot.R ├── entropy_gradient_aggregated.R ├── format_HALO_to_spe.R ├── format_cellprofiler_to_spe.R ├── format_codex_to_spe.R ├── format_colData_to_spe.R ├── format_image_to_spe.R ├── format_inform_to_spe.R ├── format_spe_to_ppp.R ├── grid_metrics.R ├── identify_bordering_cells.R ├── identify_neighborhoods.R ├── image_no_markers.R ├── image_splitter.R ├── marker_intensity_boxplot.R ├── marker_prediction_plot.R ├── marker_surface_plot.R ├── marker_surface_plot_stack.R ├── measure_association_to_cell_properties.R ├── mixing_score_summary.R ├── number_of_cells_within_radius.R ├── plot_average_intensity.R ├── plot_cell_categories.R ├── plot_cell_distances_violin.R ├── plot_cell_marker_levels.R ├── plot_cell_percentages.R ├── plot_composition_heatmap.R ├── plot_distance_heatmap.R ├── plot_marker_level_heatmap.R ├── predict_phenotypes.R ├── select_celltypes.R ├── simulated_image.R └── utils.R ├── README.md ├── data-raw ├── defined_image.R ├── image_no_markers.R └── simulated_image.R ├── data ├── defined_image.rda ├── image_no_markers.rda └── simulated_image.rda ├── inst ├── CITATION ├── extdata │ ├── tiny_cellprofiler.txt.gz │ ├── tiny_codex.csv.gz │ ├── tiny_codex_phenotypes.txt.gz │ ├── tiny_halo.csv.gz │ └── tiny_inform.txt.gz └── vignettes │ └── introduction.bib ├── man ├── AUC_of_cross_function.Rd ├── R_BC.Rd ├── SPIAT-package.Rd ├── average_marker_intensity_within_radius.Rd ├── average_minimum_distance.Rd ├── average_nearest_neighbor_index.Rd ├── average_percentage_of_cells_within_radius.Rd ├── calculate_cell_proportions.Rd ├── calculate_cross_functions.Rd ├── calculate_distance_to_margin.Rd ├── calculate_entropy.Rd ├── calculate_minimum_distances_between_celltypes.Rd ├── calculate_pairwise_distances_between_celltypes.Rd ├── calculate_percentage_of_grids.Rd ├── calculate_proportions_of_cells_in_structure.Rd ├── calculate_spatial_autocorrelation.Rd ├── calculate_summary_distances_between_celltypes.Rd ├── calculate_summary_distances_of_cells_to_borders.Rd ├── composition_of_neighborhoods.Rd ├── compute_gradient.Rd ├── crossing_of_crossK.Rd ├── define_celltypes.Rd ├── define_structure.Rd ├── defined_image.Rd ├── dimensionality_reduction_plot.Rd ├── entropy_gradient_aggregated.Rd ├── format_cellprofiler_to_spe.Rd ├── format_codex_to_spe.Rd ├── format_colData_to_spe.Rd ├── format_halo_to_spe.Rd ├── format_image_to_spe.Rd ├── format_inform_to_spe.Rd ├── format_spe_to_ppp.Rd ├── grid_metrics.Rd ├── identify_bordering_cells.Rd ├── identify_neighborhoods.Rd ├── image_no_markers.Rd ├── image_splitter.Rd ├── marker_intensity_boxplot.Rd ├── marker_prediction_plot.Rd ├── marker_surface_plot.Rd ├── marker_surface_plot_stack.Rd ├── measure_association_to_cell_properties.Rd ├── mixing_score_summary.Rd ├── number_of_cells_within_radius.Rd ├── plot_average_intensity.Rd ├── plot_cell_categories.Rd ├── plot_cell_distances_violin.Rd ├── plot_cell_marker_levels.Rd ├── plot_cell_percentages.Rd ├── plot_composition_heatmap.Rd ├── plot_distance_heatmap.Rd ├── plot_marker_level_heatmap.Rd ├── predict_phenotypes.Rd ├── select_celltypes.Rd └── simulated_image.Rd ├── tests ├── testthat.R └── testthat │ ├── test-calculations.R │ ├── test-families.R │ ├── test-plotting.R │ └── test-utilities.R └── vignettes ├── SPIAT-overview.jpg ├── SPIAT.Rmd ├── basic_analysis.Rmd ├── cell-colocalisation.Rmd ├── cross-k-function.jpg ├── data_reading-formatting.Rmd ├── marker_surface1.jpg ├── marker_surface2.jpg ├── neighborhood.Rmd ├── quality-control_visualisation.Rmd ├── spatial-heterogeneity.Rmd ├── tSNE1.jpg ├── tSNE2.jpg ├── tissue-structure.Rmd └── tumour-structure.jpg /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^.*\.Rproj$ 2 | ^\.Rproj\.user$ 3 | ^data-raw$ 4 | ^\.github 5 | ^_pkgdown\.yml$ 6 | ^doc$ 7 | ^docs$ 8 | ^Meta$ 9 | ^\.github$ 10 | docs 11 | ^Dockerfile$ 12 | ^pkgdown$ 13 | -------------------------------------------------------------------------------- /.github/.gitignore: -------------------------------------------------------------------------------- 1 | *.html 2 | -------------------------------------------------------------------------------- /.github/workflows/pkgdown.yaml: -------------------------------------------------------------------------------- 1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples 2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help 3 | on: 4 | push: 5 | branches: [RELEASE_3_20] 6 | pull_request: 7 | branches: [RELEASE_3_20] 8 | release: 9 | types: [published] 10 | workflow_dispatch: 11 | 12 | name: pkgdown 13 | 14 | jobs: 15 | pkgdown: 16 | runs-on: ubuntu-latest 17 | # Only restrict concurrency for non-PR jobs 18 | concurrency: 19 | group: pkgdown-${{ github.event_name != 'pull_request' || github.run_id }} 20 | env: 21 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 22 | steps: 23 | - uses: actions/checkout@v3 24 | 25 | - uses: r-lib/actions/setup-pandoc@v2 26 | 27 | - uses: r-lib/actions/setup-r@v2 28 | with: 29 | use-public-rspm: true 30 | 31 | - uses: r-lib/actions/setup-r-dependencies@v2 32 | with: 33 | extra-packages: any::pkgdown, local::. 34 | needs: website 35 | 36 | - name: Build site 37 | run: pkgdown::build_site_github_pages(new_process = FALSE, install = FALSE) 38 | shell: Rscript {0} 39 | 40 | - name: Deploy to GitHub pages 🚀 41 | if: github.event_name != 'pull_request' 42 | uses: JamesIves/github-pages-deploy-action@v4.4.1 43 | with: 44 | clean: false 45 | branch: gh-pages 46 | folder: docs 47 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .Rproj.user 2 | .Rhistory 3 | .RData 4 | .Ruserdata 5 | SPIAT.Rproj 6 | ^doc$ 7 | ^docs$ 8 | ^Meta$ 9 | *.DS_Store 10 | .Rprofile 11 | docs 12 | inst/doc/ 13 | .git 14 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: SPIAT 2 | Type: Package 3 | Title: Spatial Image Analysis of Tissues 4 | Version: 1.9.1 5 | Authors@R: c( 6 | person(given = "Anna", 7 | family="Trigos", 8 | role=c("aut"), 9 | comment = c(ORCID = "0000-0002-5915-2952"), 10 | email="anna.trigos@petermac.org"), 11 | person(given = "Yuzhou", 12 | family = " Feng", 13 | role=c("aut", "cre"), 14 | comment = c(ORCID = "0000-0002-2955-4053"), 15 | email="yuzhou0610@gmail.com"), 16 | person(given = "Tianpei", 17 | family = " Yang", 18 | role="aut", 19 | email="yangtp3344@gmail.com"), 20 | person(given = "Mabel", 21 | family = " Li", 22 | role="aut"), 23 | person(given = "John", 24 | family = " Zhu", 25 | role="aut"), 26 | person(given = "Volkan", 27 | family=" Ozcoban", 28 | role="aut", 29 | email = "volkanozcoban1@gmail.com"), 30 | person(given = "Maria", 31 | family= "Doyle", 32 | role="aut", 33 | email = "maria.doyle@petermac.org")) 34 | Description: SPIAT (**Sp**atial **I**mage **A**nalysis of **T**issues) is an R 35 | package with a suite of data processing, quality control, visualization and data 36 | analysis tools. SPIAT is compatible with data generated from single-cell spatial 37 | proteomics platforms (e.g. OPAL, CODEX, MIBI, cellprofiler). SPIAT reads spatial 38 | data in the form of X and Y coordinates of cells, marker intensities and cell 39 | phenotypes. SPIAT includes six analysis modules that allow visualization, 40 | calculation of cell colocalization, categorization of the immune 41 | microenvironment relative to tumor areas, analysis of cellular neighborhoods, 42 | and the quantification of spatial heterogeneity, providing a comprehensive 43 | toolkit for spatial data analysis. 44 | License: Artistic-2.0 + file LICENSE 45 | Encoding: UTF-8 46 | Depends: 47 | R (>= 4.2.0), 48 | SpatialExperiment (>= 1.8.0) 49 | Imports: 50 | apcluster (>= 1.4.7), 51 | ggplot2 (>= 3.2.1), 52 | gridExtra (>= 2.3), 53 | gtools (>= 3.8.1), 54 | reshape2 (>= 1.4.3), 55 | dplyr (>= 0.8.3), 56 | RANN (>= 2.6.1), 57 | pracma (>= 2.2.5), 58 | dbscan (>= 1.1-5), 59 | mmand (>= 1.5.4), 60 | tibble (>= 2.1.3), 61 | grDevices, 62 | stats, 63 | utils, 64 | vroom, 65 | dittoSeq, 66 | spatstat.geom, 67 | methods, 68 | spatstat.explore, 69 | raster, 70 | sp, 71 | SummarizedExperiment, 72 | rlang 73 | Suggests: 74 | BiocStyle, 75 | plotly (>= 4.9.0), 76 | knitr, 77 | rmarkdown, 78 | pkgdown, 79 | testthat, 80 | graphics, 81 | alphahull, 82 | Rtsne, 83 | umap, 84 | ComplexHeatmap, 85 | elsa 86 | biocViews: BiomedicalInformatics, CellBiology, Spatial, Clustering, DataImport, ImmunoOncology, QualityControl, SingleCell, Software, Visualization 87 | BugReports: https://github.com/trigosteam/SPIAT/issues 88 | RoxygenNote: 7.3.1 89 | LazyData: true 90 | VignetteBuilder: knitr 91 | URL: https://trigosteam.github.io/SPIAT/ 92 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | export(AUC_of_cross_function) 4 | export(R_BC) 5 | export(average_marker_intensity_within_radius) 6 | export(average_minimum_distance) 7 | export(average_nearest_neighbor_index) 8 | export(average_percentage_of_cells_within_radius) 9 | export(calculate_cell_proportions) 10 | export(calculate_cross_functions) 11 | export(calculate_distance_to_margin) 12 | export(calculate_entropy) 13 | export(calculate_minimum_distances_between_celltypes) 14 | export(calculate_pairwise_distances_between_celltypes) 15 | export(calculate_percentage_of_grids) 16 | export(calculate_proportions_of_cells_in_structure) 17 | export(calculate_spatial_autocorrelation) 18 | export(calculate_summary_distances_between_celltypes) 19 | export(calculate_summary_distances_of_cells_to_borders) 20 | export(composition_of_neighborhoods) 21 | export(compute_gradient) 22 | export(crossing_of_crossK) 23 | export(define_celltypes) 24 | export(define_structure) 25 | export(dimensionality_reduction_plot) 26 | export(entropy_gradient_aggregated) 27 | export(format_cellprofiler_to_spe) 28 | export(format_codex_to_spe) 29 | export(format_colData_to_spe) 30 | export(format_halo_to_spe) 31 | export(format_image_to_spe) 32 | export(format_inform_to_spe) 33 | export(format_spe_to_ppp) 34 | export(grid_metrics) 35 | export(identify_bordering_cells) 36 | export(identify_neighborhoods) 37 | export(image_splitter) 38 | export(marker_intensity_boxplot) 39 | export(marker_prediction_plot) 40 | export(marker_surface_plot) 41 | export(marker_surface_plot_stack) 42 | export(measure_association_to_cell_properties) 43 | export(mixing_score_summary) 44 | export(number_of_cells_within_radius) 45 | export(plot_average_intensity) 46 | export(plot_cell_categories) 47 | export(plot_cell_distances_violin) 48 | export(plot_cell_marker_levels) 49 | export(plot_cell_percentages) 50 | export(plot_composition_heatmap) 51 | export(plot_distance_heatmap) 52 | export(plot_marker_level_heatmap) 53 | export(predict_phenotypes) 54 | export(select_celltypes) 55 | import(SpatialExperiment) 56 | import(dplyr) 57 | import(ggplot2) 58 | importFrom(gridExtra,grid.arrange) 59 | importFrom(rlang,.data) 60 | importFrom(spatstat.explore,Gcross) 61 | importFrom(spatstat.explore,Jcross) 62 | importFrom(spatstat.explore,Kcross) 63 | importFrom(spatstat.explore,Kcross.inhom) 64 | importFrom(spatstat.explore,Lcross) 65 | importFrom(spatstat.geom,ppp) 66 | -------------------------------------------------------------------------------- /R/AUC_of_cross_function.R: -------------------------------------------------------------------------------- 1 | #' The difference in AUC of the cross function curves 2 | #' 3 | #' @description Calculate the difference of area under the curve (AUC) between 4 | #' two curves, normalised by the total area of the graph. 5 | 6 | #' @param df.cross Data.frame. The output of 7 | #' \code{\link{calculate_cross_functions}}. Containing the positions of the 8 | #' two curves. Columns contain "r", "border" and "theo". 9 | #' @return A number 10 | #' @export 11 | #' 12 | #' @examples 13 | #' df_cross <- calculate_cross_functions(SPIAT::defined_image, method = "Kcross", 14 | #' cell_types_of_interest = c("Tumour","Immune3"), 15 | #' feature_colname ="Cell.Type", dist = 100) 16 | #' AUC_of_cross_function(df_cross) 17 | 18 | AUC_of_cross_function <- function(df.cross){ 19 | AUC <- pracma::trapz(df.cross$r ,df.cross$border) - 20 | pracma::trapz(df.cross$r,df.cross$theo) 21 | 22 | # get the cross k result image size 23 | X <- max(df.cross$r) 24 | Y <- max(c(df.cross$theo, df.cross$border)) 25 | 26 | # calculate normalised AUC 27 | n_AUC <- AUC/(X*Y) 28 | return(n_AUC) 29 | } 30 | -------------------------------------------------------------------------------- /R/R_BC.R: -------------------------------------------------------------------------------- 1 | #' The ratio of border cell count to cluster cell count 2 | #' 3 | #' @description Calculates the ratio of the bordering cell count and the 4 | #' total to-be-clustered cell count in an image. The bordering cells are detected 5 | #' by the default \code{\link{identify_bordering_cells}} function. If the 6 | #' ratio is high, it means that most cells to be clustered are identified as bordering 7 | #' cells. This means there is no clear clusters. 8 | #' @param spe_object SpatialExperiment object in the form of the output of 9 | #' \code{\link{format_image_to_spe}}. 10 | #' @param cell_type_of_interest String. The cell type that the user wants to 11 | #' determine a cluster of. 12 | #' @param feature_colname String. The column that contains the cell type to be clustered. 13 | #' 14 | #' @return A number is returned. 15 | #' @export 16 | #' @examples 17 | #' R_BC(SPIAT::defined_image, cell_type_of_interest = "Tumour", "Cell.Type") 18 | #' 19 | R_BC <- function(spe_object, cell_type_of_interest, feature_colname){ 20 | # identify the bordering cells 21 | spe_border <- identify_bordering_cells(spe_object, 22 | reference_cell=cell_type_of_interest, 23 | feature_colname = feature_colname, 24 | ahull_alpha = 40, 25 | n_to_exclude = 0) 26 | 27 | # count the number of bordering cells and tumour cells 28 | n_cluster_cell <- count_category(spe_border, cat = cell_type_of_interest, 29 | feature_colname = feature_colname) 30 | n_border_cell <- count_category(spe_border, "Border","Region") 31 | # calculate the ratio 32 | r <- n_border_cell/n_cluster_cell 33 | 34 | return(r) 35 | } 36 | -------------------------------------------------------------------------------- /R/SPIAT-package.R: -------------------------------------------------------------------------------- 1 | #' @keywords internal 2 | "_PACKAGE" 3 | 4 | ## usethis namespace: start 5 | ## usethis namespace: end 6 | NULL 7 | -------------------------------------------------------------------------------- /R/SPIAT.R: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TrigosTeam/SPIAT/f649d7942abb70fee8c6f630b725033bc5c9524b/R/SPIAT.R -------------------------------------------------------------------------------- /R/average_marker_intensity_within_radius.R: -------------------------------------------------------------------------------- 1 | #' average_marker_intensity_within_radius 2 | #' 3 | #' @description Calculates the average intensity of the target_marker within a 4 | #' radius from the cells positive for the reference marker. Note that it pools 5 | #' all cells with the target marker that are within the specific radius of any 6 | #' reference cell. Results represent the average intensities within a radius, 7 | #' but not a vector of metrics for each cell. 8 | #' 9 | #' @param spe_object SpatialExperiment object in the form of the output of 10 | #' \code{\link{format_image_to_spe}}. 11 | #' @param reference_marker String specifying the marker that is used for 12 | #' reference cells. 13 | #' @param target_marker String specifying the marker to calculate its average 14 | #' intensity. 15 | #' @param radius Numeric specifying the radius of search for cells around the 16 | #' reference cells. 17 | #' @import dplyr 18 | #' @return A single number is returned 19 | #' @examples 20 | #' average_marker_intensity_within_radius(SPIAT::simulated_image, 21 | #' reference_marker ="Immune_marker3", 22 | #' target_marker = "Immune_marker2", 23 | #' radius=30) 24 | #' @export 25 | 26 | average_marker_intensity_within_radius <- function(spe_object, 27 | reference_marker, 28 | target_marker, 29 | radius = 20){ 30 | formatted_data <- bind_info(spe_object) 31 | 32 | #Select the cells that have the reference marker phenotype 33 | reference_cells <- formatted_data[grepl(reference_marker, 34 | formatted_data$Phenotype),] 35 | if (nrow(reference_cells) == 0) { 36 | stop("There are no reference cells found for the marker") 37 | } 38 | #Target cells are don't contain the reference marker 39 | target_cells <- formatted_data[grepl(target_marker, formatted_data$Phenotype),] 40 | if (nrow(target_cells) == 0) { 41 | stop("There are no target cells found for the marker") 42 | } 43 | 44 | #Remove cells with both markers 45 | common_cells <- reference_cells$Cell.ID[reference_cells$Cell.ID 46 | %in% target_cells$Cell.ID] 47 | reference_cells <- reference_cells[!(reference_cells$Cell.ID 48 | %in% common_cells),] 49 | target_cells <- target_cells[!(target_cells$Cell.ID %in% common_cells),] 50 | 51 | #Get the coordinates to find neighbours 52 | reference_cell_cords <- reference_cells[,c("Cell.X.Position", 53 | "Cell.Y.Position")] 54 | target_cell_cords <- target_cells[,c("Cell.X.Position", "Cell.Y.Position")] 55 | 56 | #frNN output ids, the rowid of reference_cell_cords matches the row number of target_cell_cords 57 | search_result <- dbscan::frNN(target_cell_cords, eps = radius, 58 | query = reference_cell_cords, sort = FALSE) 59 | rownums <- unique(unlist(search_result$id)) 60 | 61 | #check 62 | if (length(rownums) == 0) { 63 | stop("There are no target cells within the specified radius, cannot calculate average intensity") 64 | } else { 65 | target_within_radius <- target_cells[rownums,] 66 | average_marker_intensity <- mean(target_within_radius[,target_marker], 67 | na.rm=TRUE)} 68 | return(average_marker_intensity) 69 | } 70 | -------------------------------------------------------------------------------- /R/average_minimum_distance.R: -------------------------------------------------------------------------------- 1 | #' average_minimum_distance 2 | #' 3 | #' @description Calculates the average minimum distance of all cells to their 4 | #' nearest cells in the input image. 5 | #' 6 | #' @param spe_object SpatialExperiment object in the form of the output of 7 | #' \code{\link{format_image_to_spe}}. 8 | #' @import dplyr 9 | #' @return A single number is returned 10 | #' @examples 11 | #' average_minimum_distance(SPIAT::simulated_image) 12 | #' @export 13 | 14 | average_minimum_distance <- function(spe_object) { 15 | 16 | formatted_data <- get_colData(spe_object) 17 | 18 | #extract the cell coordinates 19 | all_cell_cords <- formatted_data[,c("Cell.X.Position", "Cell.Y.Position")] 20 | 21 | #CHECK 22 | if (nrow(all_cell_cords) == 0) { 23 | stop("No cells found in average minimum distance calculation") 24 | } 25 | 26 | #calculate the closest 2 neighbours, 1st being itself 27 | all_closest <- RANN::nn2(data = all_cell_cords, k = 2) 28 | 29 | #grab the distances and find the average 30 | all_closest_dist <- all_closest$nn.dists[,2] 31 | average_min_distance <- mean(all_closest_dist) 32 | 33 | return(average_min_distance) 34 | } 35 | -------------------------------------------------------------------------------- /R/average_nearest_neighbor_index.R: -------------------------------------------------------------------------------- 1 | #' Average nearest neighbor index for point pattern (clustering or dispersion) 2 | #' 3 | #' @description Calculate the the average nearest neighbor (ANN) index of a 4 | #' specified type of cells. The index indicates the clustering effect of a 5 | #' point pattern. The pattern can be clustering, random or dispersion. 6 | #' @details ANN index is a statistical test to test for the presence of clusters 7 | #' of cells, (Clark and Evans, 1954). The ANN index evaluates the spatial 8 | #' aggregation or dispersion effect of objects based on the average distances 9 | #' between pairs of the nearest objects and can be used to test for the 10 | #' clustering of specific cell types (e.g. immune or tumor cells). Next, the z 11 | #' score and p-value of the ANN index is calculated to validate the 12 | #' significance of the pattern. 13 | #' 14 | #' @param spe_object SpatialExperiment object in the form of the output of 15 | #' \code{\link{format_image_to_spe}}. 16 | #' @param reference_celltypes String Vector. Cells with these cell types will be 17 | #' used for ANNI calculation. 18 | #' @param feature_colname String. Specify the selected column for 19 | #' `reference_celltypes`. 20 | #' @param p_val Numeric. The p value threshold to determine the significance of 21 | #' a pattern. 22 | #' @export 23 | #' @return A list with the ANN index, the pattern type and the corresponding p 24 | #' value 25 | #' @examples 26 | #' average_nearest_neighbor_index(SPIAT::defined_image, reference_celltypes = 27 | #' "Tumour", feature_colname = "Cell.Type") 28 | 29 | average_nearest_neighbor_index <- function(spe_object, reference_celltypes, 30 | feature_colname, p_val = 5e-6){ 31 | 32 | ppp <- format_spe_to_ppp(spe_object) 33 | formatted_data <- get_colData(spe_object) 34 | 35 | data <- formatted_data[,c(feature_colname,"Cell.X.Position", 36 | "Cell.Y.Position")] 37 | data <- data[which(data[,feature_colname] %in% reference_celltypes), 38 | c("Cell.X.Position","Cell.Y.Position") ] 39 | 40 | if(nrow(data) == 0){ 41 | methods::show("No reference cells found") 42 | output <- list(ANN_index=NA, pattern=NA,`p-value`=NA) 43 | }else{ 44 | object<-format_colData_to_spe(data) 45 | 46 | ppp_object <- format_spe_to_ppp(object) 47 | ann.p <- mean(spatstat.geom::nndist(ppp_object, k=1)) 48 | 49 | n <- ppp_object$n # Number of points 50 | 51 | x <- ppp$window$xrange[2] - ppp$window$xrange[1] 52 | y <- ppp$window$yrange[2] - ppp$window$yrange[1] 53 | area <- x*y 54 | ann.e <- 0.5/sqrt(n/area) 55 | ANN_index <- ann.p/ann.e 56 | se <- 0.26136/sqrt(n*n/area) 57 | z <- (ann.p - ann.e)/se 58 | p <- stats::pnorm(-abs(z)) 59 | 60 | if (p <= p_val){ 61 | if (ann.p <= ann.e){ 62 | pattern <- "Clustered" 63 | } 64 | else{pattern <- "Dispersed"} 65 | } 66 | else{pattern <- "Random"} 67 | 68 | output <- list(ANN_index, pattern, p) 69 | names(output) <- c("ANN_index", "pattern" ,"p-value") 70 | } 71 | return(output) 72 | } 73 | -------------------------------------------------------------------------------- /R/average_percentage_of_cells_within_radius.R: -------------------------------------------------------------------------------- 1 | #' average_percentage_of_cells_within_radius 2 | #' 3 | #' @description Calculates the average percentage of cells of a target cell type 4 | #' within a radius from the cells with a reference cell type. The calculation 5 | #' is done per reference cell, so runtime will depend on the number of 6 | #' reference cells present. Output is a single value (the mean for the image). 7 | #' 8 | #' @param spe_object SpatialExperiment object in the form of the output of 9 | #' \code{\link{format_image_to_spe}}. 10 | #' @param reference_celltype String specifying the cell type of reference 11 | #' cells. 12 | #' @param target_celltype String specifying the cell type for target cells 13 | #' @param radius Integer specifying the radius of search for cells around the 14 | #' reference cells. Radii of ~100 are recommended. If too small, too few cells 15 | #' might be present. 16 | #' @param feature_colname String specifying the column with the desired cell 17 | #' type annotations. 18 | #' @import dplyr 19 | #' @return A numeric vector and a plot are returned 20 | #' @examples 21 | #' average_percentage_of_cells_within_radius(SPIAT::defined_image, "Tumour", 22 | #' "Immune3", radius = 100, "Cell.Type") 23 | #' @export 24 | 25 | average_percentage_of_cells_within_radius <- function(spe_object, 26 | reference_celltype, 27 | target_celltype, 28 | radius = 100, 29 | feature_colname){ 30 | # setting these variables to NULL as otherwise get "no visible binding for global variable" in R check 31 | phenotype_names <- output_phenotype <- NULL 32 | formatted_data <- get_colData(spe_object) 33 | #Select cells with the reference phenotype 34 | reference_celltypes <- formatted_data[formatted_data[,feature_colname] 35 | == reference_celltype,] 36 | target_celltypes <- formatted_data[formatted_data[,feature_colname] 37 | == target_celltype,] 38 | 39 | #CHECK 40 | if (nrow(reference_celltypes) == 0 || nrow(target_celltypes) == 0) { 41 | methods::show("There are no reference cells or no target cells") 42 | return(NA) 43 | }else{ 44 | #get the coordinates to find neighbours 45 | reference_cell_cords <- reference_celltypes[,c("Cell.X.Position", 46 | "Cell.Y.Position")] 47 | 48 | #frNN output ids 49 | search_result <- dbscan::frNN(formatted_data[,c("Cell.X.Position", 50 | "Cell.Y.Position")], 51 | eps = radius, query = reference_cell_cords, 52 | sort = FALSE) 53 | rownums <- unique(unlist(search_result$id)) 54 | 55 | #CHECK 56 | if (length(rownums) == 0) { 57 | methods::show("There are no target cells within the radius") 58 | return(NA) 59 | } else { 60 | output_percentage <- vector() 61 | cell_IDs <- vector() 62 | 63 | for(cell in names(search_result$id)){ 64 | radius_cells <- search_result$id[[cell]] 65 | radius_cells <- radius_cells[radius_cells != cell] 66 | radius_cells <- formatted_data[radius_cells,] 67 | 68 | percentage <- (nrow(radius_cells[radius_cells$Cell.ID %in% 69 | target_celltypes$Cell.ID, ]) 70 | /nrow(radius_cells))*100 71 | output_percentage <- c(output_percentage, percentage) 72 | cell_IDs <- c(cell_IDs, formatted_data[cell,"Cell.ID"]) 73 | } 74 | names(output_percentage) <- cell_IDs 75 | } 76 | return(mean(output_percentage)) 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /R/calculate_cell_proportions.R: -------------------------------------------------------------------------------- 1 | #' calculate_cell_proportions 2 | #' 3 | #' @description Calculates the number and proportion of each cell type. 4 | #' 5 | #' @param spe_object SpatialExperiment object in the form of the output of 6 | #' \code{\link{format_image_to_spe}}. 7 | #' @param reference_celltypes String Vector specifying reference cell types. If 8 | #' NULL (default), then the proportion of each cell type against all cells is 9 | #' returned. Alternatively, a custom vector of cell types can be used as 10 | #' input, and these will be used as the denominator in the calculation of the 11 | #' proportions. 12 | #' @param celltypes_to_exclude String Vector specifying cell types to exclude. 13 | #' For example "OTHER" will exclude that celltype from the Total. If NULL, all 14 | #' cell types are included. 15 | #' @param feature_colname String. Column of cells to choose the cell type from 16 | #' (e.g. Phenotype, Cell.Type, etc). 17 | #' @param plot.image Boolean. Whether to plot the barplot of the cell percentages. 18 | #' By default is TRUE. 19 | #' @import ggplot2 20 | #' @return A data.frame is returned 21 | #' @examples 22 | #' calculate_cell_proportions(SPIAT::defined_image, reference_celltypes = NULL, 23 | #' celltypes_to_exclude = "Others", feature_colname="Cell.Type", plot.image = FALSE) 24 | #' @export 25 | 26 | calculate_cell_proportions <- function(spe_object, reference_celltypes = NULL, 27 | celltypes_to_exclude = NULL, 28 | feature_colname="Phenotype",plot.image = TRUE){ 29 | Cell_type <- Percentage <- NULL 30 | #Reads the image file and deletes cell rows with NA positions 31 | cell_loc <- get_colData(spe_object) 32 | 33 | #CHECK 34 | if (nrow(cell_loc) == 0) { 35 | stop("No cells found for calculating cell proportions")} 36 | 37 | #Creates frequency/bar plot of all cell types in the entire image 38 | cell_proportions <- as.data.frame(table(cell_loc[,feature_colname])) 39 | names(cell_proportions)[1] <- 'Cell_type' 40 | names(cell_proportions)[2] <- 'Number_of_celltype' 41 | 42 | #Exclude any phenotypes not wanted 43 | if (!is.null(celltypes_to_exclude)) { 44 | for (celltype in celltypes_to_exclude) { 45 | cell_proportions <- 46 | cell_proportions[!grepl(celltype, 47 | cell_proportions[["Cell_type"]]), ] 48 | }} 49 | if(is.null(reference_celltypes)){ 50 | celltype_cells <- cell_proportions 51 | celltype_cells_total <- sum(celltype_cells$Number_of_celltype) 52 | celltype_cells$Proportion <- celltype_cells$Number_of_celltype/celltype_cells_total 53 | celltype_cells$Percentage <- celltype_cells$Proportion*100 54 | celltype_cells$Proportion_name <- paste(celltype_cells[[feature_colname]], 55 | "Total", sep="/") 56 | cell_proportions$Reference <- "Total" 57 | cell_proportions <- celltype_cells 58 | 59 | }else{ 60 | celltype_cells <- cell_proportions 61 | celltype_cells_total <- 62 | sum(celltype_cells$Number_of_celltype[celltype_cells[[feature_colname]] 63 | %in% reference_celltypes]) 64 | celltype_cells$Proportion <- celltype_cells$Number_of_celltype/celltype_cells_total 65 | celltype_cells$Percentage <- celltype_cells$Proportion*100 66 | celltype_cells$Proportion_name <- paste(celltype_cells[[feature_colname]], 67 | "Custom", sep="/") 68 | cell_proportions <- celltype_cells 69 | cell_proportions$Reference <- paste(reference_celltypes, collapse=",") 70 | } 71 | 72 | #order by Reference celltype (reverse to have Total first if present) then by highest proportion 73 | cell_proportions <- cell_proportions[rev(order(cell_proportions$Proportion)), ] 74 | 75 | if(plot.image){ 76 | g <- ggplot(cell_proportions, aes(x=Cell_type, y=Percentage)) + 77 | geom_bar(stat='identity') + theme_bw() 78 | methods::show(g)} 79 | 80 | return(cell_proportions) 81 | } 82 | -------------------------------------------------------------------------------- /R/calculate_cross_functions.R: -------------------------------------------------------------------------------- 1 | #' calculate_cross_functions 2 | #' 3 | #' @description Compute and plot the cross functions between two specified cell 4 | #' types. This function implements the cross functions from [spatstat] package. 5 | #' 6 | #' @param spe_object SpatialExperiment object in the form of the output of 7 | #' \code{\link{format_image_to_spe}}. 8 | #' @param method String that is the method for dependence calculation. Options: 9 | #' "Gcross", "Kcross", "Kcross.inhom", "Lcross", "Jcross". Default method is 10 | #' "Kcross". 11 | #' @param cell_types_of_interest String Vector. Cell types of interest. 12 | #' @param feature_colname String that is the name of the column of the types. 13 | #' @param plot_results Boolean. TRUE if result to be plotted, FALSE if not. In 14 | #' either case, an object with the results is returned 15 | #' @param dist Number (OPTIONAL) The largest distance between two cell types at 16 | #' which K function is evaluated. If NULL, use the default distances set by 17 | #' cross functions. 18 | #' @importFrom spatstat.explore Gcross Kcross.inhom Lcross Jcross Kcross 19 | #' @importFrom spatstat.geom ppp 20 | #' @return An object of class "fv" defined in `spatstat` package. 21 | #' @export 22 | #' @examples 23 | #' df_cross <- calculate_cross_functions(SPIAT::defined_image, 24 | #' method = "Kcross", cell_types_of_interest = c("Tumour","Immune3"), 25 | #' feature_colname ="Cell.Type", dist = 100) 26 | 27 | calculate_cross_functions <- function(spe_object, method = "Kcross", 28 | cell_types_of_interest, feature_colname, 29 | plot_results = TRUE, dist = NULL) { 30 | #CHECK 31 | formatted_data <-get_colData(spe_object) 32 | if (!all(cell_types_of_interest %in% formatted_data[[feature_colname]])) { 33 | stop("Cell type not found!") 34 | } 35 | 36 | # format spe to ppp object 37 | ppp_object <- format_spe_to_ppp(spe_object, 38 | feature_colname = feature_colname) 39 | ppp_object$marks <- as.factor(ppp_object$marks) 40 | 41 | # r 42 | if (is.null(dist)) r <- NULL 43 | else r <- seq(0, dist, length.out = 100) 44 | 45 | if (method == "Gcross"){ 46 | p <- Gcross(ppp_object, cell_types_of_interest[1], 47 | cell_types_of_interest[2],correction = "border", r = r) 48 | if(plot_results){ 49 | plot(p, main = paste("cross G function",attr(spe_object,"name"))) 50 | } 51 | } 52 | else if (method == "Kcross"){ 53 | p <- Kcross(ppp_object, cell_types_of_interest[1], 54 | cell_types_of_interest[2],correction = "border", r = r) 55 | if(plot_results){ 56 | if (is.null(dist)) plot(p, main = paste("cross K function", 57 | attr(spe_object,"name"))) 58 | else plot(p, main = paste("cross K function", 59 | attr(spe_object,"name")), 60 | xlim = c(0,dist)) 61 | } 62 | } 63 | else if (method == "Kcross.inhom"){ 64 | p <- Kcross.inhom(ppp_object, cell_types_of_interest[1], 65 | cell_types_of_interest[2],correction = "border", 66 | r = r) 67 | if(plot_results){ 68 | if (is.null(dist)) plot(p, main = paste("cross K function", 69 | attr(spe_object,"name"))) 70 | else plot(p, main = paste("cross K function", 71 | attr(spe_object,"name")), 72 | xlim = c(0,dist)) 73 | } 74 | } 75 | else if (method == "Lcross"){ 76 | p <- Lcross(ppp_object, cell_types_of_interest[1], 77 | cell_types_of_interest[2],correction = "border", r = r) 78 | if(plot_results){ 79 | plot(p, main = paste("cross L function",attr(spe_object,"name"))) 80 | } 81 | } 82 | else if (method == "Jcross"){ 83 | p <- Jcross(ppp_object, cell_types_of_interest[1], 84 | cell_types_of_interest[2],correction = "border", r = r) 85 | if(plot_results){ 86 | plot(p, main = paste("cross J function",attr(spe_object,"name"))) 87 | } 88 | } 89 | return(p) 90 | } 91 | -------------------------------------------------------------------------------- /R/calculate_distance_to_tumour_margin.R: -------------------------------------------------------------------------------- 1 | #' calculate the distances of each cell to the margin 2 | #' 3 | #' @description Returns a SPE object with the minimum distance from cells of 4 | #' interest (CoI) to the identified bordering cells. 5 | #' 6 | #' @param spe_object SpatialExperiment object. It should contain information of 7 | #' the detected bordering cells (`colData()` has `Region` column). 8 | #' @return An spe_object with a `Distance.To.Border` column is returned. 9 | #' @export 10 | #' @examples 11 | #' spe_border <- identify_bordering_cells(SPIAT::defined_image, 12 | #' reference_cell = "Tumour", feature_colname = "Cell.Type", n_to_exclude = 10) 13 | #' spe_dist <- calculate_distance_to_margin(spe_border) 14 | 15 | calculate_distance_to_margin <- function(spe_object){ 16 | 17 | #CHECK if the user has found the bordering cells yet 18 | if (is.null(spe_object$Region)){ 19 | stop("Please find the bordering cells first! (use identify_bordering_cells)") 20 | } 21 | 22 | dat <- get_colData(spe_object) 23 | 24 | #CHECK 25 | if (nrow(dat) == 0) { 26 | stop("There are no cells") 27 | } 28 | 29 | dat <- dat[, c("Cell.ID","Region", "Cell.X.Position", "Cell.Y.Position")] 30 | dat <- dat[dat$Region != "",] 31 | 32 | spe_object <- define_celltypes( 33 | spe_object, categories = c("Outside","Inside","Border"), 34 | category_colname ="Region", 35 | names = c("Non-border","Non-border","Border"), new_colname = "region2") 36 | 37 | dist_matrix <- calculate_minimum_distances_between_celltypes( 38 | spe_object, cell_types_of_interest = c("Non-border","Border"), 39 | feature_colname ="region2") 40 | dist_matrix[dist_matrix$RefType == "Border", "Distance"] <- 0 41 | dist_matrix$Order <- as.numeric(substr(dist_matrix$RefCell, 42 | start = 6, stop = 30)) 43 | dist_matrix <- dist_matrix[order(dist_matrix$Order),] 44 | dat <- merge(dat, dist_matrix,by.x = "Cell.ID",by.y = "RefCell", 45 | all.x = TRUE, sort = FALSE) 46 | SummarizedExperiment::colData(spe_object)$Distance.To.Border <- dat$Dist 47 | 48 | return(spe_object) 49 | } 50 | -------------------------------------------------------------------------------- /R/calculate_entropy.R: -------------------------------------------------------------------------------- 1 | #' calculate_entropy 2 | #' 3 | #' @description If arg `radius` is not specified, the function returns the 4 | #' entropy of the cell types of interest for the whole image. If arg `radius` 5 | #' is specified, the function returns a data frame where each row is a 6 | #' reference cell and the columns stores the entropy of the cell types of 7 | #' interest in each circle of the reference cells. 8 | #' @param spe_object SpatialExperiment object in the form of the output of 9 | #' \code{\link{format_image_to_spe}}. 10 | #' @param cell_types_of_interest String Vector. Cell types of interest. If arg 11 | #' `radius` is not NULL, the first cell type is considered as reference cell 12 | #' type. Circles of the specified radius will be drawn around the reference 13 | #' cells and the entropy of cell types will be calculated for each of the 14 | #' reference cells. 15 | #' @param feature_colname String specifying the column the cell types are from. 16 | #' @param radius (OPTIONAL) Numeric. The maximum radius around a reference cell 17 | #' for another cell to be considered an interaction. 18 | #' @return A dataframe or a number depending on the argument radius 19 | #' @export 20 | #' @examples 21 | #' calculate_entropy(SPIAT::defined_image, 22 | #' cell_types_of_interest = c("Immune1","Immune2"), 23 | #' feature_colname = "Cell.Type") 24 | 25 | calculate_entropy <- function(spe_object, cell_types_of_interest, 26 | feature_colname = "Phenotype", radius = NULL){ 27 | 28 | if((cell_types_of_interest[1] %in% 29 | SummarizedExperiment::colData(spe_object)[,feature_colname]) && 30 | any(cell_types_of_interest[-1] %in% 31 | SummarizedExperiment::colData(spe_object)[,feature_colname])){ 32 | if (!is.null(radius)){ 33 | reference_marker <- cell_types_of_interest[1] 34 | target_marker<-cell_types_of_interest 35 | n_cells <- number_of_cells_within_radius( 36 | spe_object, reference_celltype = reference_marker, 37 | target_celltype = target_marker,radius = radius, 38 | feature_colname = feature_colname) 39 | n_cells.df <- n_cells[[reference_marker]] 40 | n_cells.df[,"total"] <- 0 41 | 42 | for (i in target_marker){ 43 | n_cells.df[,paste(i,"_log2",sep = "")] <- log2(n_cells.df[,i]) 44 | n_cells.df[,"total"] <- n_cells.df[,"total"]+n_cells.df[,i]} 45 | n_cells.df[,"total_log2"] <- log2(n_cells.df[,"total"]) 46 | n_cells.df[n_cells.df == -Inf] <- 0 47 | 48 | for (i in target_marker){ 49 | n_cells.df[which(n_cells.df[,"total"] != 0), 50 | paste(i,"ratio",sep = "")] <- 51 | n_cells.df[,i]/n_cells.df[,"total"] 52 | n_cells.df[which(n_cells.df[,"total"] == 0), 53 | paste(i,"ratio",sep = "")] <- 0 54 | n_cells.df[,paste(i,"_entropy",sep = "")] <- 55 | n_cells.df[, paste(i,"ratio",sep = "")] * 56 | (n_cells.df[,paste(i,"_log2",sep = "")] - 57 | n_cells.df[,"total_log2"])} 58 | n_cells.df[,"entropy"] <- 59 | -(rowSums(n_cells.df[,grepl("_entropy",colnames(n_cells.df))])) 60 | 61 | return(n_cells.df)} else{ 62 | entropy_all <- 0 63 | data <- data.frame(SummarizedExperiment::colData(spe_object)) 64 | data <- data[which(data[,feature_colname] %in% 65 | cell_types_of_interest),] 66 | n_all <- dim(data)[1] 67 | 68 | if (n_all == 0){ 69 | return(0.0)} else{ 70 | for (type in cell_types_of_interest){ 71 | type_data <- data[which(data[,feature_colname]==type),] 72 | n_type <- dim(type_data)[1] 73 | if (n_type != 0){ 74 | p_type <- n_type/n_all 75 | entropy_type <- -(p_type)*log2(p_type) 76 | entropy_all <- entropy_all + entropy_type}} 77 | return(entropy_all)}}}else{ 78 | methods::show("Cell type not found!") 79 | return(NA)}} 80 | -------------------------------------------------------------------------------- /R/calculate_pairwise_distances_between_celltypes.R: -------------------------------------------------------------------------------- 1 | #' calculate_pairwise_distances_between_celltypes 2 | #' 3 | #' @description Returns the pairwise distances between cells of different types. 4 | #' If none of the cell types are found, it will print an error message and 5 | #' return a vector of NAs. 6 | #' @param spe_object SpatialExperiment object in the form of the output of 7 | #' \code{\link{format_image_to_spe}}. 8 | #' @param cell_types_of_interest String Vector containing cell types to be 9 | #' considered, if NULL, all cell type combinations will be calculated. 10 | #' @param feature_colname String of the name the feature column with the cell 11 | #' types of interest to be considered. 12 | #' @import dplyr 13 | #' @return A data.frame is returned. 14 | #' @examples 15 | #' calculate_pairwise_distances_between_celltypes(SPIAT::defined_image, 16 | #' cell_types_of_interest = c("Tumour","Immune1"), 17 | #' feature_colname = "Cell.Type") 18 | #' @export 19 | 20 | calculate_pairwise_distances_between_celltypes <- function( 21 | spe_object, cell_types_of_interest = NULL, feature_colname){ 22 | 23 | #Reads the image file and deletes cell rows with NA positions 24 | dat <- get_colData(spe_object) 25 | 26 | #Selects all rows in the data file which only contains the cells of interest 27 | if(!is.null(cell_types_of_interest)){ 28 | unique_cell_types_selected <- cell_types_of_interest 29 | dat <- dat[dat[, feature_colname] %in% unique_cell_types_selected,] 30 | } 31 | 32 | #CHECK 33 | if (nrow(dat) == 0) { 34 | methods::show("There are no cells or no cells of specified cell types") 35 | cell_to_cell_dist_all <- c(Cell1 = NA, Cell2 = NA, Distance = NA, 36 | Pair = NA, Type1 = NA, Type2 = NA) 37 | }else{ 38 | dat <- dat[,c("Cell.ID", feature_colname, "Cell.X.Position", 39 | "Cell.Y.Position")] 40 | 41 | #Creates a list of the number of cell types with all their 42 | #corresponding cell ID's 43 | cell_types <- list() 44 | for (eachType in unique(dat[, feature_colname])) { 45 | cell_types[[eachType]] <- as.character( 46 | dat$Cell.ID[dat[, feature_colname] == eachType]) 47 | } 48 | 49 | cell_id_vector <- dat$Cell.ID 50 | 51 | #Calculates cell to cell distances 52 | dist_all <- -apcluster::negDistMat(dat[,c("Cell.X.Position", 53 | "Cell.Y.Position")]) 54 | colnames(dist_all) <- cell_id_vector 55 | rownames(dist_all) <- cell_id_vector 56 | 57 | cell_to_cell_dist_all <- vector() 58 | for(cell_name1 in names(cell_types)){ 59 | for(cell_name2 in names(cell_types)){ 60 | cell_ids1 <- cell_types[[cell_name1]] 61 | cell_ids2 <- cell_types[[cell_name2]] 62 | if(length(cell_ids1) >= 3 & length(cell_ids2) >=3){ 63 | cell_to_cell <- dist_all[cell_id_vector %in% cell_ids1, 64 | cell_id_vector %in% cell_ids2] 65 | #Melts dist_all to produce dataframe of target and nearest 66 | #cell ID's columns and distance column 67 | cell_to_cell_dist <- reshape2::melt(cell_to_cell) 68 | cell_to_cell_dist$Type1 <- cell_name1 69 | cell_to_cell_dist$Type2 <- cell_name2 70 | cell_to_cell_dist$Pair <- paste(cell_name1, 71 | cell_name2,sep="/") 72 | 73 | if(cell_name1 == cell_name2){ 74 | cell_to_cell_dist$value[ 75 | cell_to_cell_dist$value == 0] <- NA 76 | } 77 | colnames(cell_to_cell_dist)[3] <- "Distance" 78 | cell_to_cell_dist_all <- rbind(cell_to_cell_dist_all, 79 | cell_to_cell_dist) 80 | } 81 | } 82 | } 83 | # remove NAs e.g. for distance of cell against itself 84 | cell_to_cell_dist_all <- 85 | cell_to_cell_dist_all[stats::complete.cases(cell_to_cell_dist_all),] 86 | colnames(cell_to_cell_dist_all)[c(1,2)] <- c("Cell1", "Cell2") 87 | } 88 | 89 | return(cell_to_cell_dist_all) 90 | } 91 | -------------------------------------------------------------------------------- /R/calculate_percentage_of_grids.R: -------------------------------------------------------------------------------- 1 | #' calculate_percentage_of_grids 2 | #' 3 | #' @description Takes the result of \code{\link{grid_metrics}} (a RasterLayer 4 | #' object) and calculates the percentage of the grid squares whose values are 5 | #' above or below a specified threshold. 6 | #' 7 | #' @param raster_obj Raster object in the form of the output of 8 | #' \code{\link{grid_metrics}}. 9 | #' @param threshold Numeric. The threshold for defining the pattern. 10 | #' @param above Boolean. Indicating whether the pattern is above (TRUE) or below 11 | #' (FALSE) the threshold. 12 | #' @export 13 | #' @return A number is returned 14 | #' @examples 15 | #' grid <- grid_metrics(SPIAT::defined_image, FUN = calculate_entropy, n_split = 5, 16 | #' cell_types_of_interest=c("Tumour","Immune3"), feature_colname = "Cell.Type") 17 | #' calculate_percentage_of_grids(grid, threshold = 0.75, above = TRUE) 18 | 19 | calculate_percentage_of_grids <- function(raster_obj, threshold, above){ 20 | raster_obj@data@values[is.na(raster_obj@data@values)] <- 0 21 | if (above) { 22 | p <- sum(raster_obj@data@values>=threshold)/ 23 | length(raster_obj@data@values) * 100 24 | } 25 | else { 26 | p <- sum(raster_obj@data@values% 30 | group_by(Pair) %>% 31 | summarise(mean(Distance, na.rm = TRUE), min(Distance, na.rm = TRUE), 32 | max(Distance, na.rm = TRUE), 33 | stats::median(Distance, na.rm = TRUE), 34 | stats::sd(Distance, na.rm = TRUE)) 35 | 36 | summarised_dists <- data.frame(summarised_dists) 37 | colnames(summarised_dists) <- c("Pair" , "Mean", "Min", "Max", 38 | "Median", "Std.Dev") 39 | 40 | for (i in seq(1,dim(summarised_dists)[1])){ 41 | cellnames <- strsplit(summarised_dists[i,"Pair"],"/")[[1]] 42 | summarised_dists[i, "Reference"] <- cellnames[1] 43 | summarised_dists[i, "Target"] <- cellnames[2] 44 | } 45 | return(summarised_dists) 46 | } 47 | -------------------------------------------------------------------------------- /R/calculate_summary_distances_of_cells_to_borders.R: -------------------------------------------------------------------------------- 1 | #' calculate_summary_distances_of_cells_to_borders 2 | #' 3 | #' @description Returns the mean, median and standard deviation of the distances 4 | #' between a specified cell type to the border. 5 | #' @param spe_object SpatialExperiment object. It should contain information of 6 | #' tissue structure and cell distances to the tissue region border (`colData()` has 7 | #' `Region` and `Distance.To.Border` columns). 8 | #' @param cell_types_of_interest String Vector of cell types to consider. 9 | #' @param feature_colname String specifying which column the interested cell 10 | #' types are from. 11 | #' @return A data.frame is returned 12 | #' @export 13 | #' @examples 14 | #' spe_border <- identify_bordering_cells(SPIAT::defined_image, 15 | #' reference_cell = "Tumour", feature_colname = "Cell.Type", n_to_exclude = 10) 16 | #' spe_dist <- calculate_distance_to_margin(spe_border) 17 | #' spe_structure <- define_structure(spe_dist, cell_types_of_interest = 18 | #' c("Immune1","Immune2","Immune3"), feature_colname = "Cell.Type", 19 | #' n_margin_layers = 5) 20 | #' calculate_summary_distances_of_cells_to_borders(spe_structure, 21 | #' cell_types_of_interest = c("Immune1","Immune3"),feature_colname = "Cell.Type") 22 | 23 | calculate_summary_distances_of_cells_to_borders <- function( 24 | spe_object, cell_types_of_interest, feature_colname = "Cell.Type") { 25 | 26 | # CHECK if "Region" and "Distance.To.Border" columns exist 27 | if (is.null(spe_object$Region)){ 28 | stop("Find the bordering cells first! Use the function identifying_bordering_cells_interactive()") 29 | } 30 | if (is.null(spe_object$Distance.To.Border)){ 31 | stop("Find the min distances to the bordering cells first! Use the function calculate_min_distances_to_borders()") 32 | } 33 | 34 | # CHECK input 35 | if (is.null(cell_types_of_interest)){ 36 | stop("Please indicate the cell types!") 37 | } 38 | if (is.null(feature_colname)){ 39 | stop("Please indicate the column name of the cell types!") 40 | } 41 | 42 | data <- data.frame(SummarizedExperiment::colData(spe_object)) 43 | 44 | # define a function to get the statistics of the distances 45 | summarise_dist <- function(data){ 46 | if (dim(data)[1] == 0){ 47 | min_d <- max_d <- mean_d <- median_d <- st.dev_d <- NA 48 | } 49 | else { 50 | min_d <- min(data$Distance.To.Border, na.rm = TRUE) 51 | max_d <- max(data$Distance.To.Border, na.rm = TRUE) 52 | mean_d <- mean(data$Distance.To.Border, na.rm = TRUE) 53 | median_d <- stats::median(data$Distance.To.Border, na.rm = TRUE) 54 | st.dev_d <- stats::sd(data$Distance.To.Border, na.rm = TRUE) 55 | } 56 | return(c(min_d, max_d, mean_d, median_d, st.dev_d)) 57 | } 58 | ##### data in ##### 59 | data_of_interest_in <- 60 | data[which((data[[feature_colname]] %in% cell_types_of_interest) 61 | & (data$Region == "Inside")),] 62 | 63 | df.cols <- c("Cell.Type", "Location", "Min", "Max", "Mean", 64 | "Median", "St.dev") 65 | df <- vector() 66 | 67 | sum_d <- summarise_dist(data_of_interest_in) 68 | 69 | df <- rbind(df, c("All_cell_types_of_interest", "Within_border_area", sum_d)) 70 | ##### data out ##### 71 | data_of_interest_out <- 72 | data[which((data[[feature_colname]] %in% cell_types_of_interest) 73 | & (data$Region == "Outside")),] 74 | 75 | sum_d <- summarise_dist(data_of_interest_out) 76 | 77 | df <- rbind(df, c("All_cell_types_of_interest", "Stroma", sum_d)) 78 | 79 | for(type in cell_types_of_interest){ 80 | data_of_interest_in <- data[which((data[[feature_colname]] %in% type) & 81 | (data$Region == "Inside")),] 82 | sum_d <- summarise_dist(data_of_interest_in) 83 | 84 | df <- rbind(df, c(type, "Within_border_area", sum_d)) 85 | ##### data out ##### 86 | data_of_interest_out <- data[which((data[[feature_colname]] %in% type) & 87 | (data$Region == "Outside")),] 88 | sum_d <- summarise_dist(data_of_interest_out) 89 | 90 | df <- rbind(df, c(type, "Stroma", sum_d)) 91 | } 92 | colnames(df) <- c("Cell.Type", "Area", "Min_d", "Max_d", "Mean_d", 93 | "Median_d", "St.dev_d") 94 | df <- as.data.frame(df) 95 | df$Min_d <- as.numeric(df$Min_d) 96 | df$Max_d <- as.numeric(df$Max_d) 97 | df$Mean_d <- as.numeric(df$Mean_d) 98 | df$Median_d <- as.numeric(df$Median_d) 99 | df$St.dev_d <- as.numeric(df$St.dev_d) 100 | return(df) 101 | } 102 | -------------------------------------------------------------------------------- /R/composition_of_neighborhoods.R: -------------------------------------------------------------------------------- 1 | #' composition_of_neighborhoods 2 | #' 3 | #' @description Returns a data.frame which contains the percentages of cells 4 | #' with a specific marker within each neighborhood. and the number of cells in 5 | #' the neighborhood. 6 | #' @param spe_object SpatialExperiment that is the output of 7 | #' \code{\link{identify_neighborhoods}}. 8 | #' @param feature_colname String. Column with cell types. 9 | #' @return A data.frame is returned 10 | #' @examples 11 | #' neighborhoods <- identify_neighborhoods(image_no_markers, 12 | #' method = "hierarchical", min_neighborhood_size = 100, 13 | #' cell_types_of_interest = c("Immune", "Immune1", "Immune2"), radius = 50, 14 | #' feature_colname = "Cell.Type") 15 | #' neighborhoods_vis <- composition_of_neighborhoods(neighborhoods, 16 | #' feature_colname="Cell.Type") 17 | #' @export 18 | 19 | composition_of_neighborhoods <- function(spe_object, feature_colname) { 20 | 21 | neighborhoods_df <- get_colData(spe_object) 22 | neighborhoods_df <- 23 | neighborhoods_df[stats::complete.cases(neighborhoods_df),] 24 | 25 | number_of_clusters <- length(unique(neighborhoods_df[,"Neighborhood"])) 26 | 27 | colnames(neighborhoods_df)[colnames(neighborhoods_df) == feature_colname] <- 28 | "Temp_pheno" 29 | 30 | composition <- stats::aggregate(Cell.ID ~ Temp_pheno + Neighborhood, 31 | neighborhoods_df, length) 32 | colnames(composition)[3] <- "Number_of_cells" 33 | cluster_size <- table(neighborhoods_df$Neighborhood) 34 | composition$Total_number_of_cells <- 35 | as.vector(cluster_size[match(composition$Neighborhood, 36 | names(cluster_size))]) 37 | 38 | composition$Percentage <- 39 | (composition$Number_of_cells/composition$Total_number_of_cells)*100 40 | colnames(composition)[colnames(composition) == "Temp_pheno"] <- 41 | feature_colname 42 | return(composition) 43 | } 44 | -------------------------------------------------------------------------------- /R/compute_gradient.R: -------------------------------------------------------------------------------- 1 | #' compute_gradient 2 | #' 3 | #' @description The function sweeps over circles of a range of radii surrounding 4 | #' reference cells and calculates the metrics at the radii. Metrics used with 5 | #' function need two conditions: 1) have a `radius` parameter. 2) return a 6 | #' single number. For metrics that do not return a single number, users can 7 | #' wrap them in a new function that returns a number and then pass the new 8 | #' function to `compute_gradient()`. 9 | #' @param spe_object SpatialExperiment object in the form of the output of 10 | #' \code{\link{format_image_to_spe}}. 11 | #' @param radii Numeric Vector specifying the range of radii for the metrics to 12 | #' be calculated. 13 | #' @param FUN Variable name specifying the metric. 14 | #' @param ... Arguments of FUN 15 | #' @return A list of the metrics under all radii 16 | #' @export 17 | #' 18 | #' @examples 19 | #' gradient_positions <- c(30, 50, 100) 20 | #' gradient_entropy <- compute_gradient(SPIAT::defined_image, 21 | #' radii = gradient_positions, FUN = calculate_entropy, 22 | #' cell_types_of_interest = c("Immune1","Immune2"), 23 | #' feature_colname = "Cell.Type") 24 | 25 | compute_gradient <- function(spe_object, radii, FUN, ...){ 26 | list.metric <- list() 27 | for (i in seq_len(length(radii))){ 28 | metric <- FUN(spe_object,radius = radii[i], ...) 29 | list.metric[[i]] <- metric 30 | } 31 | return(list.metric) 32 | } 33 | -------------------------------------------------------------------------------- /R/crossing_of_crossK.R: -------------------------------------------------------------------------------- 1 | #' crossing_of_crossK 2 | #' 3 | #' @description Determine if there is a crossing in the cross K curves, to 4 | #' further detect the existence of potential immune rings. 5 | #' 6 | #' @param df.cross Data.frame. The output of 7 | #' \code{\link{calculate_cross_functions}}. Containing the positions of the 8 | #' two curves. Columns contain "r", "border" and "theo". 9 | #' 10 | #' @return A number. The percentage of the crossing position of the specified 11 | #' distance. Returns NA when the crossing happens too close to the y axis (<4%). 12 | #' @export 13 | #' 14 | #' @examples 15 | #' df_cross <- calculate_cross_functions(SPIAT::defined_image, method="Kcross", 16 | #' cell_types_of_interest = c("Tumour","Immune3"), 17 | #' feature_colname ="Cell.Type", dist = 100) 18 | #' crossing_of_crossK(df_cross) 19 | 20 | crossing_of_crossK <- function(df.cross){ 21 | df.cross$sign <- df.cross$theo - df.cross$border 22 | change_of_sign <- diff(sign(df.cross$sign[-1])) 23 | ix <- which(change_of_sign != 0) 24 | n <- dim(df.cross)[1] 25 | if (length(ix) == 1 && ix/n > 0.04){ 26 | methods::show("Crossing of cross K function is detected for this image, indicating a potential immune ring.") 27 | perc <- round(ix/n *100,2) 28 | methods::show(paste("The crossing happens at the ", 29 | perc, "% of the specified distance.", sep = "")) 30 | } 31 | else ix <- NA 32 | return(round(1-ix/n,2)) 33 | } 34 | -------------------------------------------------------------------------------- /R/define_celltypes.R: -------------------------------------------------------------------------------- 1 | #' define_celltypes 2 | #' 3 | #' @description Define new cell types based on the existing cell types 4 | #' (categories) under a selected column (e.g. base on marker combinations 5 | #' under "Phenotype" column). This function will create a new column to store 6 | #' the new cell types. 7 | #' 8 | #' @details Users need to specify the names of the old cell categories and under 9 | #' which column the old cell categories exist. Then the users specify the 10 | #' names of the new cell types and the name of the new column to store the new 11 | #' cell types. Any cell categories that are not specified in `categories` arg 12 | #' but present in the image will be defined as "Undefined" in the new column. 13 | #' 14 | #' @param spe_object SpatialExperiment object in the form of the output of 15 | #' \code{\link{format_image_to_spe}}. 16 | #' @param categories Vector. Names of the old cell types to be defined; if NULL, 17 | #' the function will use predefined categories and names 18 | #' @param category_colname (Phenotype) String specifying the name of the column 19 | #' having the categories to be defined, by default "Phenotype". 20 | #' @param names Vector of new names assigned to the selected categories; if 21 | #' NULL, the function will use predefined categories and names. Should be of 22 | #' the same length of `categories`. 23 | #' @param new_colname (Optional) String specifying the name of the column to be 24 | #' added, by default "Cell.Type". 25 | #' @param print_names (Optional) Boolean if the user wants the original and new 26 | #' names printed. Default is FALSE. 27 | #' @export 28 | #' @return An new SPE object is returned 29 | #' @examples 30 | #' # the selected column is: 31 | #' category_colname = "Phenotype" 32 | #' # define the following marker combinations: 33 | #' categories <- c("Tumour_marker", "Immune_marker1,Immune_marker2", 34 | #' "Immune_marker1,Immune_marker3", 35 | #' "Immune_marker1,Immune_marker2,Immune_marker4", "OTHER") 36 | #' # the new defined cell names: 37 | #' names = c("Tumour", "Immune1", "Immune2","Immune3", "Others") 38 | #' # the new names are stored under this column: 39 | #' new_colname <- "Cell.Type" 40 | #' 41 | #' defined_spe <- define_celltypes(SPIAT::simulated_image, 42 | #' categories = categories, category_colname = category_colname, names = names, 43 | #' new_colname = new_colname) 44 | 45 | define_celltypes <- function(spe_object,categories = NULL, 46 | category_colname = "Phenotype", names = NULL, 47 | new_colname = "Cell.Type", print_names = FALSE){ 48 | 49 | # CHECK 50 | if (length(categories) != length(names)){ 51 | methods::show("`length(categories) != length(names)`") 52 | stop("The old and new cell type names should be of the same length!") 53 | } 54 | # default setting 55 | if (is.null(categories) & is.null(names)){ 56 | pre_categories <- c("AMACR", "CD3,CD4", "CD3,CD8", "CD3", 57 | "AMACR,PDL-1","PDL-1") 58 | pre_names <- c("Tumour","CD4","CD8","CD3","Tumour,PDL1","PDL1") 59 | } 60 | 61 | else{ 62 | pre_categories <- categories 63 | pre_names <- names 64 | } 65 | 66 | all_categories <- 67 | unique(SummarizedExperiment::colData(spe_object)[[category_colname]]) 68 | categories <- intersect(all_categories, pre_categories) 69 | names <- pre_names[match(categories, pre_categories)] 70 | 71 | if (print_names){ 72 | methods::show(paste("Define new cell types basing on:", categories)) 73 | methods::show(paste("The new cell types are:",names)) 74 | } 75 | 76 | spe_object[[new_colname]] <- "" 77 | names<- c(names,rep("Undefined",length(all_categories[ 78 | !(all_categories %in% categories)]))) 79 | categories <- c(categories,all_categories[ 80 | !(all_categories %in% categories)]) 81 | for (i in seq_len(length(categories))){ 82 | spe_object[,spe_object[[category_colname]] == 83 | categories[i]][[new_colname]] <- names[i] 84 | } 85 | 86 | return(spe_object) 87 | } 88 | 89 | -------------------------------------------------------------------------------- /R/defined_image.R: -------------------------------------------------------------------------------- 1 | #' SPE object of a simulated image with defined cell types based on marker 2 | #' combinations. 3 | #' 4 | #' A dataset that contains a formatted spe object with cell ids, phenotypes, 5 | #' defined cell types in `colData()` and marker intensities in `assays()`. (The 6 | #' cell locations are the same with the cells in \code{\link{simulated_image}}). 7 | #' 8 | #' @format An spe object. Assay contains 5 rows (markers) and 4951 columns 9 | #' (cells); colData contains 4951 rows (cells) and 3 columns (features). 10 | #' @seealso \code{\link{simulated_image}} \code{\link{image_no_markers}} 11 | "defined_image" 12 | -------------------------------------------------------------------------------- /R/dimensionality_reduction_plot.R: -------------------------------------------------------------------------------- 1 | #' Dimensionality reduction plot 2 | #' 3 | #' @description Generates the dimensionality reduction plots (UMAP or tSNE) 4 | #' based on marker intensities. Cells are grouped by the categories under the 5 | #' selected column. 6 | #' @param spe_object SpatialExperiment object in the form of the output of 7 | #' \code{\link{format_image_to_spe}}. 8 | #' @param plot_type String. Choose from "UMAP" and "TSNE". 9 | #' @param scale Boolean. Whether scale the marker intensities. 10 | #' @param perplexity Numeric. Perplexity parameter of the Rtsne function (should 11 | #' be positive and no bigger than 3 * perplexity < n - 1, where n is the 12 | #' number of cells). 13 | #' @param feature_colname String. Specify the column name to group the cells. 14 | #' 15 | #' @return A plot 16 | #' @export 17 | #' @examples 18 | #' dimensionality_reduction_plot(SPIAT::simulated_image, plot_type = "TSNE", 19 | #' feature_colname = "Phenotype") 20 | dimensionality_reduction_plot <- function(spe_object, plot_type = "UMAP", 21 | scale=TRUE, 22 | perplexity = 30, feature_colname){ 23 | requireNamespace("plotly", quietly = TRUE) 24 | Cell_ID <- dim_X <- dim_Y <- Label <- NULL 25 | formatted_data <- get_colData(spe_object) 26 | 27 | intensity_matrix <- SummarizedExperiment::assay(spe_object) 28 | intensity_matrix_no_DAPI <- 29 | intensity_matrix[rownames(intensity_matrix) != "DAPI",] 30 | 31 | if(scale){ 32 | intensity_matrix_no_DAPI_scaled <- scale(t(intensity_matrix_no_DAPI)) 33 | }else{ 34 | intensity_matrix_no_DAPI_scaled <- t(intensity_matrix_no_DAPI) 35 | } 36 | 37 | if(plot_type == "UMAP"){ 38 | if (dim(formatted_data)[1] <= 14){ 39 | stop("The image should contain at least 15 cells to plot UMAP.") 40 | } 41 | requireNamespace("umap", quietly = TRUE) 42 | intensity_DR <- umap::umap(intensity_matrix_no_DAPI_scaled) 43 | intensity_DR_layout <- as.data.frame(intensity_DR$data) 44 | colnames(intensity_DR_layout) <- c("dim_X", "dim_Y") 45 | intensity_DR_layout$Label <- 46 | formatted_data[[feature_colname]][ 47 | match(rownames(intensity_DR_layout), formatted_data$Cell.ID)] 48 | 49 | }else if (plot_type == "TSNE"){ 50 | if (dim(formatted_data)[1] <= 4){ 51 | stop("The image should contain at least 5 cells to plot TSNE plot.") 52 | } 53 | if (3 * perplexity > nrow(formatted_data)- 1){ 54 | perplexity <- floor((nrow(formatted_data)-1)/3) 55 | warning("The perplexity for tsne has been changed to ", perplexity, 56 | " due to the small cell count in the image.") 57 | } 58 | requireNamespace("Rtsne", quietly = TRUE) 59 | intensity_DR <- Rtsne::Rtsne(intensity_matrix_no_DAPI_scaled, 60 | check_duplicates = FALSE, 61 | perplexity = perplexity) 62 | intensity_DR_layout <- as.data.frame(intensity_DR$Y) 63 | colnames(intensity_DR_layout) <- c("dim_X", "dim_Y") 64 | rownames(intensity_DR_layout) <- 65 | rownames(intensity_matrix_no_DAPI_scaled) 66 | intensity_DR_layout$Label <- 67 | formatted_data[[feature_colname]][ 68 | match(rownames(intensity_DR_layout), formatted_data$Cell.ID)] 69 | 70 | }else{ 71 | methods::show("Print select UMAP or TSNE as plot type") 72 | } 73 | 74 | intensity_DR_layout$Cell_ID <- rownames(intensity_DR_layout) 75 | 76 | g <- ggplot(intensity_DR_layout, aes(x=dim_X, y=dim_Y, label=Cell_ID))+ 77 | geom_point(aes(colour=Label))+ 78 | ggtitle(plot_type)+ 79 | theme_bw()+ 80 | theme(panel.grid.major = element_blank()) 81 | plotly::ggplotly(g) 82 | 83 | return(g) 84 | } 85 | -------------------------------------------------------------------------------- /R/entropy_gradient_aggregated.R: -------------------------------------------------------------------------------- 1 | #' The aggregated gradient of entropy and the peak of the gradient 2 | #' 3 | #' @description This function first calculates the entropy within circles of 4 | #' each reference cell at each radius. Then at each radius, the entropy of all 5 | #' circles surrounding each cell are aggregated into one number. The function 6 | #' sweeps over the specified radii and calculates the aggregated entropy under 7 | #' each radius. 8 | #' 9 | #' @param spe_object SpatialExperiment object in the form of the output of 10 | #' \code{\link{format_image_to_spe}}. 11 | #' @param cell_types_of_interest String Vector. The cell types that the entropy 12 | #' is computed on. 13 | #' @param feature_colname String. The column name of the interested cell types. 14 | #' @param radii Numeric Vector. A vector of radii within a circle of a reference 15 | #' cell where the entropy is computed on. 16 | #' @import dplyr 17 | #' 18 | #' @return A list of the gradient of entropy and the peak 19 | #' @export 20 | #' 21 | #' @examples 22 | #' gradient_pos <- seq(50, 500, 50) 23 | #' gradient_results <- entropy_gradient_aggregated(SPIAT::defined_image, 24 | #' cell_types_of_interest = c("Tumour","Immune3"), 25 | #' feature_colname = "Cell.Type", radii = gradient_pos) 26 | #' plot(1:10,gradient_results$gradient_df[1, 3:12]) 27 | entropy_gradient_aggregated <- function(spe_object, cell_types_of_interest, 28 | feature_colname, radii){ 29 | 30 | # entropy_pairs <- vector() 31 | gradient_aggregated <- vector() 32 | 33 | for(pheno1 in cell_types_of_interest){ 34 | for(pheno2 in cell_types_of_interest){ 35 | if(pheno2 != pheno1){ 36 | unique_types <- unique(SummarizedExperiment::colData(spe_object) 37 | [,feature_colname]) 38 | if((pheno1 %in% unique_types) && (pheno2 %in% unique_types)){ 39 | # get the gradient 40 | gradient_local <- compute_gradient( 41 | spe_object, radii = radii,number_of_cells_within_radius, 42 | reference_celltype = pheno1, 43 | target_celltype = c(pheno1, pheno2), 44 | feature_colname = feature_colname) 45 | 46 | 47 | gradient_local_aggregated <- vector() 48 | # aggregate all tumour and immune counts and calculate new aggragated "entropy" 49 | for(j in seq_len(length(gradient_local))){ 50 | temp <- gradient_local[[j]] 51 | total_reference <- sum(temp[[pheno1]][[pheno1]]) 52 | total_target <- sum(temp[[pheno1]][[pheno2]]) 53 | total_cells <- total_reference + total_target 54 | reference_disorder <- (total_reference/total_cells) * 55 | log2(total_reference/total_cells) 56 | target_disorder <- (total_target/total_cells) * 57 | log2(total_target/total_cells) 58 | local_entropy <- -(reference_disorder+target_disorder) 59 | gradient_local_aggregated <- 60 | c(gradient_local_aggregated,local_entropy) 61 | 62 | } 63 | gradient_aggregated <- rbind( 64 | gradient_aggregated,c(pheno1, pheno2, 65 | gradient_local_aggregated)) 66 | } 67 | else{ 68 | gradient_local_aggregated <- 69 | c(pheno1, pheno2, rep(NA, length(radii))) 70 | gradient_aggregated <- rbind(gradient_aggregated, 71 | gradient_local_aggregated) 72 | }}}} 73 | 74 | # format the output 75 | colnames(gradient_aggregated) <- c("Celltype1", "Celltype2", 76 | paste("Pos", radii, sep="_")) 77 | gradient_aggregated <- as.data.frame(gradient_aggregated) 78 | gradient_aggregated[,3:(length(radii) + 2)] <- 79 | apply(gradient_aggregated[,3:(length(radii) + 2)], 2, 80 | function(x){as.numeric(as.character(x))}) 81 | rownames(gradient_aggregated) <- NULL 82 | 83 | # get the peak of the gradient 84 | temp <- gradient_aggregated[1,] 85 | temp$Celltype1 <- NULL 86 | temp$Celltype2 <- NULL 87 | temp <- as.numeric(temp) 88 | peak <- which(temp == max(temp, na.rm = TRUE)) 89 | 90 | return(list(gradient_df = gradient_aggregated, peak = peak)) 91 | } 92 | -------------------------------------------------------------------------------- /R/format_codex_to_spe.R: -------------------------------------------------------------------------------- 1 | #' Format a CODEX image into a SpatialExperiment object 2 | #' 3 | #' @description Reads in spatial data in the form of cell coordinates, cell 4 | #' phenotypes (if available), and marker intensities and transforms to a 5 | #' `SpatialExperiment` object. The assay stores the intensity level of every marker 6 | #' (rows) for every cell (columns). Cell phenotype is stored under colData. 7 | #' Cell x and y coordinates are stored under `spatialCoords()` field. 8 | #' @export 9 | #' @param path String of the path location of CODEX csv file. 10 | #' @param markers String Vector containing the markers used for staining. 11 | #' @param path_to_codex_cell_phenotypes String of the path to 12 | #' the Cluster ID/Cell type file. 13 | #' @return A SpatialExperiment object is returned 14 | #' @examples 15 | #' path <- system.file("extdata", "tiny_codex.csv.gz", package = "SPIAT") 16 | #' path_to_codex_cell_phenotypes <- system.file("extdata", 17 | #' "tiny_codex_phenotypes.txt.gz", package = "SPIAT") 18 | #' markers <- c("CD45", "Ly6C", "CD27", "CD5", "CD79b") 19 | #' formatted_codex <- format_codex_to_spe(path = path, markers = markers, 20 | #' path_to_codex_cell_phenotypes = path_to_codex_cell_phenotypes) 21 | 22 | format_codex_to_spe <- function(path = NULL, markers, 23 | path_to_codex_cell_phenotypes = NULL){ 24 | phenotypes <- utils::read.delim(path_to_codex_cell_phenotypes,header=FALSE) 25 | colnames(phenotypes) <- c("Cluster_ID", "Cell_type") 26 | 27 | data <- utils::read.delim(path, sep=",") 28 | data$Cell_type <- phenotypes$Cell_type[match(data$Imaging.phenotype.cluster.ID, 29 | phenotypes$Cluster_ID)] 30 | data$Imaging.phenotype.cluster.ID <- NULL 31 | data$niche.cluster.ID <- NULL 32 | data$sample_Xtile_Ytile <- NULL 33 | data$Z.Z <- NULL 34 | 35 | coordinates <- data[,c("X.X", "Y.Y")] 36 | data$X.X <- NULL 37 | data$Y.Y <- NULL 38 | phenotype <- data$Cell_type 39 | data$Cell_type <- NULL 40 | rownames(data) <- paste("Cell", rownames(data), sep="_") 41 | data <- t(data) 42 | 43 | metadata_columns <- data.frame(Phenotype = phenotype, 44 | Cell.X.Position = coordinates$X.X, 45 | Cell.Y.Position = coordinates$Y.Y) 46 | 47 | spe <- SpatialExperiment::SpatialExperiment( 48 | assay = data, 49 | colData = metadata_columns, 50 | spatialCoordsNames = c("Cell.X.Position", "Cell.Y.Position")) 51 | 52 | rownames(spe) <- markers 53 | 54 | return(spe) 55 | } 56 | -------------------------------------------------------------------------------- /R/format_colData_to_spe.R: -------------------------------------------------------------------------------- 1 | #' format_colData_to_spe 2 | #' 3 | #' @description Format a data frame into a SpatialExperiment class where the 4 | #' count assay is empty every cell (columns), cell phenotypes are stored under 5 | #' colData() and cell coordinates are stored under spatialCoords(). 6 | #' 7 | #' @param df Data frame that contains cell coordinates, phenotypes (if 8 | #' available) and other cell properties. The rownames should be cell ID 9 | #' @return An SpatialExperiment object 10 | #' @examples 11 | #' df <- data.frame(row.names = c("Cell_1", "Cell_2"), Cell.X.Position = c(2,5), 12 | #' Cell.Y.Position = c(3.3, 8), Phenotypes = c("CD3", "CD3,CD8")) 13 | #' spe <- format_colData_to_spe(df) 14 | #' @export 15 | 16 | format_colData_to_spe <- function(df) { 17 | 18 | #CHECK 19 | if (dim(df)[1]==0){ 20 | stop("No data in the dataframe") 21 | } 22 | 23 | assay_data <- rep(0, dim(df)[1]) 24 | assay_rownames <- "pseudo" 25 | assay_colnames <- rownames(df) 26 | 27 | #transpose the matrix so every column is a cell and every row is a marker 28 | assay_data_matrix <- as.matrix(assay_data) 29 | colnames(assay_data_matrix) <- NULL 30 | rownames(assay_data_matrix) <- NULL 31 | assay_data_matrix_t <- t(assay_data_matrix) 32 | 33 | spe <- SpatialExperiment::SpatialExperiment( 34 | assays = assay_data_matrix_t, colData = df, 35 | spatialCoordsNames = c("Cell.X.Position", "Cell.Y.Position")) 36 | 37 | rownames(spe) <- assay_rownames 38 | colnames(spe) <- assay_colnames 39 | 40 | return(spe) 41 | } 42 | -------------------------------------------------------------------------------- /R/format_spe_to_ppp.R: -------------------------------------------------------------------------------- 1 | #' Format SPE object as a ppp object (`spatstat` package) 2 | #' 3 | #' @description Formats an spe object into a ppp object which has the x,y 4 | #' coordinates, phenotypes as markers window specifies the range of x and y 5 | #' coordinates 6 | #' 7 | #' @export 8 | #' @param spe_object SpatialExperiment object in the form of the output of 9 | #' format_image_to_spe. 10 | #' @param window_pol Optional Boolean Specifying if the window is polygon. 11 | #' @param feature_colname String specifying the feature column of interest. 12 | #' @return A ppp object is returned (defined in `spatstat` package) 13 | #' @examples 14 | #' ppp_object<-format_spe_to_ppp(SPIAT::defined_image, 15 | #' feature_colname = "Cell.Type") 16 | 17 | format_spe_to_ppp <- function(spe_object, window_pol = FALSE, 18 | feature_colname="Phenotype") { 19 | 20 | # get x, y coordinates and phenotypes from spe object 21 | spe_data <- get_colData(spe_object) 22 | spe_data <- spe_data[!duplicated(spe_data[,c("Cell.X.Position", 23 | "Cell.Y.Position")]),] 24 | x <- spe_data$Cell.X.Position 25 | y <- spe_data$Cell.Y.Position 26 | marks <- spe_data[[feature_colname]] 27 | 28 | # get windows 29 | x_summary <- summary(spe_data$Cell.X.Position) 30 | x_min <- as.numeric(x_summary[1]) 31 | x_max <- as.numeric(x_summary[6]) 32 | y_summary <- summary(spe_data$Cell.Y.Position) 33 | y_min <- as.numeric(y_summary[1]) 34 | y_max <- as.numeric(y_summary[6]) 35 | 36 | if (window_pol == TRUE){ 37 | 38 | # get ploy window 39 | X <- data.frame(x,y) 40 | hpts <- grDevices::chull(X) 41 | poly_window <- list(x=rev(X[hpts, 1]), y=rev(X[hpts, 2])) 42 | 43 | # format spe to ppp 44 | ppp_object <- spatstat.geom::ppp(x, y, poly = poly_window, 45 | marks = marks) 46 | } 47 | 48 | else{ 49 | ppp_object <- spatstat.geom::ppp( 50 | x, y, window = spatstat.geom::owin(c(x_min, x_max),c(y_min, y_max)), 51 | marks = marks)} 52 | return(ppp_object) 53 | } 54 | -------------------------------------------------------------------------------- /R/grid_metrics.R: -------------------------------------------------------------------------------- 1 | #' Split an image into grid and calculates a metric for each grid square 2 | #' 3 | #' @description Calculates a specified metric for each grid tile in the image 4 | #' and plots the metrics for the grid tiles. 5 | #' @param spe_object SpatialExperiment object in the form of the output of 6 | #' \code{\link{format_image_to_spe}}. 7 | #' @param n_split Integer specifying the number of splits for the calculation of 8 | #' metrics. This number is the splits on each side (e.g. `n_split` = 3 means 9 | #' the image will be split into 9 tiles.) 10 | #' @param FUN Variable name specifying the metric to be calculated. 11 | #' @param ... Arguments of FUN 12 | #' @return A list of the metrics of all grid tiles 13 | #' @export 14 | #' @examples 15 | #' grid <- grid_metrics(SPIAT::defined_image, FUN = calculate_entropy, n_split = 5, 16 | #' cell_types_of_interest=c("Tumour","Immune3"), feature_colname = "Cell.Type") 17 | 18 | grid_metrics <- function(spe_object, FUN, n_split, ...){ 19 | split <- image_splitter(spe_object,n_split) 20 | list.metric <- list() 21 | for (i in seq_len(length(split))){ 22 | spe <- split[[i]] 23 | if(is.na(spe)){spe <- NULL} 24 | if (methods::is(spe,"SpatialExperiment")){ 25 | metric <- quiet_basic(FUN(spe, ...)) 26 | if (length(metric)==0){ 27 | metric <- 0.0 28 | } 29 | list.metric[[i]] <- metric 30 | } 31 | else{ 32 | list.metric[[i]] <- 0.0 33 | } 34 | } 35 | x <- raster::raster(ncol=n_split, nrow=n_split, xmn=0, ymn=0, 36 | xmx=max(SpatialExperiment::spatialCoords(spe_object)[,"Cell.X.Position"]), 37 | ymx=max(SpatialExperiment::spatialCoords(spe_object)[,"Cell.X.Position"])) 38 | raster::values(x) <- unlist(list.metric) 39 | y <- raster::flip(x, direction='y') 40 | raster::plot(y, main = paste("Plot ",attr(spe_object, "name"), " ",as.character(substitute(FUN)), 41 | sep = "")) 42 | 43 | return(y) 44 | } 45 | 46 | -------------------------------------------------------------------------------- /R/image_no_markers.R: -------------------------------------------------------------------------------- 1 | #' SPE object of a formatted image without marker intensities (simulated by 2 | #' `spaSim` package) 3 | #' 4 | #' A dataset that contains a formatted spe object with cell ids and cell types 5 | #' in `colData()` and cell coordinates in `spatialCoords()`. This dataset does 6 | #' not contain assays (marker intensities). 7 | #' 8 | #' @format An spe object. colData contains 4951 rows (cells) and 3 columns 9 | #' (features). 10 | #' @seealso \code{\link{defined_image}} \code{\link{simulated_image}} 11 | "image_no_markers" 12 | -------------------------------------------------------------------------------- /R/marker_intensity_boxplot.R: -------------------------------------------------------------------------------- 1 | #' marker_intensity_boxplot 2 | #' 3 | #' @description Produces boxplots of marker levels for cells phenotyped as being 4 | #' positive for the marker, and those that where phenotyped as being negative. 5 | #' @param spe_object SpatialExperiment object in the form of the output of 6 | #' \code{\link{format_image_to_spe}}. 7 | #' @param marker String. Marker being queried. 8 | #' @param feature_colname String. Column containing marker information 9 | #' @import dplyr 10 | #' @import ggplot2 11 | #' @return A plot is returned 12 | #' @examples 13 | #' marker_intensity_boxplot(SPIAT::simulated_image, "Immune_marker1") 14 | #' @export 15 | 16 | marker_intensity_boxplot <- function(spe_object, marker, feature_colname = "Phenotype"){ 17 | # setting these variables to NULL as otherwise get "no visible binding for global variable" in R check 18 | intensity <- NULL 19 | 20 | formatted_data <- bind_info(spe_object) 21 | 22 | #selecting cells that do express the marker 23 | intensity_true <- formatted_data[grepl(marker, formatted_data[[feature_colname]]), ] 24 | 25 | #selecting cells that do not contain the marker 26 | intensity_false <- formatted_data[!grepl(marker, formatted_data[[feature_colname]]), ] #for multiple entries that does not contain marker 27 | 28 | #select the specific marker and add a boolean of intensity 29 | if (nrow(intensity_true) != 0) { 30 | intensity_true$intensity <- "P" 31 | } else{ 32 | stop(sprintf("There are no cells positive for %s", marker)) 33 | } 34 | 35 | if (nrow(intensity_false) != 0){ 36 | intensity_false$intensity <- "N" 37 | } else{ 38 | stop(sprintf("There are no cells negative for %s", marker)) 39 | } 40 | 41 | #bind the 2 dataframes together 42 | intensity_by_marker <- rbind(intensity_true, intensity_false) 43 | intensity_by_marker$intensity <- factor(intensity_by_marker$intensity, levels=c("P", "N")) 44 | 45 | #plot boxplot 46 | title <- paste("Level of ", marker, sep="") 47 | 48 | #code from ggplot2 to show the number in each group 49 | give.n <- function(x){ 50 | return(c(y = max(x)+1, label = length(x))) 51 | } 52 | 53 | p <- ggplot(intensity_by_marker, aes(x = intensity, y = intensity_by_marker[, marker])) 54 | p <- p + geom_boxplot() 55 | p <- p + labs(title = title, x = "Marker status (Positive/Negative cell)", y = "Marker level") 56 | p <- p + stat_summary(fun.data = give.n, geom = "text") 57 | p <- p + theme_bw() 58 | 59 | # methods::show(p) 60 | return(p) 61 | } 62 | -------------------------------------------------------------------------------- /R/marker_prediction_plot.R: -------------------------------------------------------------------------------- 1 | #' marker_prediction_plot 2 | #' 3 | #' @description Takes in the returned dataframe from marker_threshold_plot and 4 | #' generates a .pdf file containing scatter plots of actual intensity and 5 | #' predicted intensity for every marker. 6 | #' 7 | #' @param predicted_data Output from \code{\link{predict_phenotypes}}. 8 | #' @param marker String. Marker to plot 9 | #' @import ggplot2 10 | #' @return A plot is returned 11 | #' @examples 12 | #' predicted_result <- predict_phenotypes(spe_object = simulated_image, thresholds = NULL, 13 | #' tumour_marker = "Tumour_marker",baseline_markers = c("Immune_marker1", "Immune_marker2", 14 | #' "Immune_marker3", "Immune_marker4"), reference_phenotypes = TRUE) 15 | #' marker_prediction_plot(predicted_result, marker = "Tumour_marker") 16 | #' @export 17 | 18 | marker_prediction_plot <- function(predicted_data, marker) { 19 | 20 | # setting these variables to NULL as otherwise get "no visible binding for global variable" in R check 21 | Cell.X.Position <- Cell.Y.Position <- NULL 22 | 23 | #get the markers 24 | actual_phenotype_colnames <- predicted_data[grepl("_actual_phenotype", colnames(predicted_data))] 25 | markers <- gsub("_actual_phenotype", "", actual_phenotype_colnames) 26 | 27 | #extract the actual and predicted intensity status along with X and Y cord 28 | actual_colname <- paste(marker, "_actual_phenotype", sep="") 29 | predicted_colname <- paste(marker, "_predicted_phenotype", sep="") 30 | 31 | actual <- predicted_data[,c("Cell.X.Position", "Cell.Y.Position", actual_colname)] 32 | pred <- predicted_data[,c("Cell.X.Position", "Cell.Y.Position", predicted_colname)] 33 | 34 | #plot actual intensity status 35 | title_actual <- paste("Actual intensity status of ", marker, sep="") 36 | p_actual <- ggplot(actual, aes(x = Cell.X.Position, y = Cell.Y.Position, color = as.character(actual[,3]))) + 37 | geom_point(size = 0.1) + scale_color_manual(values=c('grey','red')) + 38 | guides(alpha = "none") + labs(colour = "Intensity status") + ggtitle(title_actual) + 39 | theme(panel.grid.major = element_blank(), 40 | panel.grid.minor = element_blank(), 41 | panel.background = element_rect(fill = "white"), 42 | axis.title.x = element_blank(), 43 | axis.text.x = element_blank(), 44 | axis.ticks.x = element_blank(), 45 | axis.title.y = element_blank(), 46 | axis.text.y = element_blank(), 47 | axis.ticks.y = element_blank()) 48 | 49 | #plot predicted intensity status 50 | title_pred <- paste("Predicted intensity status of ", marker, sep="") 51 | p_pred <- ggplot(pred, aes(x = Cell.X.Position, y = Cell.Y.Position, color = as.character(pred[,3]))) + 52 | geom_point(size = 0.1) + scale_color_manual(values=c('grey','red')) + 53 | guides(alpha = "none") + labs(colour = "Intensity status") + ggtitle(title_pred) + 54 | theme(panel.grid.major = element_blank(), 55 | panel.grid.minor = element_blank(), 56 | panel.background = element_rect(fill = "white"), 57 | axis.title.x = element_blank(), 58 | axis.text.x = element_blank(), 59 | axis.ticks.x = element_blank(), 60 | axis.title.y = element_blank(), 61 | axis.text.y = element_blank(), 62 | axis.ticks.y = element_blank()) 63 | gridExtra::grid.arrange(p_actual, p_pred, nrow=1) 64 | } 65 | -------------------------------------------------------------------------------- /R/number_of_cells_within_radius.R: -------------------------------------------------------------------------------- 1 | #' Number of cells within a radius 2 | #' 3 | #' @description Calculates the number of cells of a target cell type 4 | #' within a pre-defined radius around cells of a reference cell type. 5 | #' @param spe_object SpatialExperiment object in the form of the output of 6 | #' \code{\link{format_image_to_spe}}. 7 | #' @param reference_celltype String. Cell type to be used for reference cells. 8 | #' @param target_celltype String. Cell type to be used for target cells. 9 | #' @param radius Numeric. Radius around the reference cells. 10 | #' @param feature_colname String specifying the column with the desired cell 11 | #' type annotations. 12 | #' @import dplyr 13 | #' @return A list of dataframes with the number of target cells of each of the 14 | #' reference cells 15 | #' @export 16 | #' @examples 17 | #' n_in_radius <- number_of_cells_within_radius(SPIAT::defined_image, 18 | #' reference_celltype = "Tumour", target_celltype="Immune1", radius = 50, 19 | #' feature_colname = "Cell.Type") 20 | 21 | number_of_cells_within_radius <- function(spe_object, reference_celltype, 22 | target_celltype, radius = 20, 23 | feature_colname) 24 | { 25 | formatted_data <- get_colData(spe_object) 26 | 27 | all.df <- list() 28 | for (i in reference_celltype) { 29 | reference_cells <- formatted_data[which(formatted_data[,feature_colname] == i), ] 30 | reference_cell_cords <- reference_cells[, c("Cell.ID", "Cell.X.Position","Cell.Y.Position")] 31 | dataframe <- tibble::remove_rownames(reference_cell_cords) 32 | dataframe <- dataframe %>% tibble::column_to_rownames("Cell.ID") 33 | reference_cell_cords <- reference_cells[, c( "Cell.X.Position","Cell.Y.Position")] 34 | for (j in target_celltype) { 35 | target_cells <- formatted_data[which(formatted_data[,feature_colname] == j), ] 36 | target_cell_cords <- target_cells[, c("Cell.ID", "Cell.X.Position","Cell.Y.Position")] 37 | target_cell_cords <- tibble::remove_rownames(target_cell_cords) 38 | target_cell_cords <- target_cell_cords %>% tibble::column_to_rownames("Cell.ID") 39 | reference_target_result <- dbscan::frNN(target_cell_cords, eps = radius, 40 | query = reference_cell_cords, sort =FALSE) 41 | n_targets <- rapply(reference_target_result$id, length) 42 | dataframe[,j] <- n_targets 43 | } 44 | all.df[[i]] <- dataframe 45 | } 46 | return(all.df) 47 | } 48 | -------------------------------------------------------------------------------- /R/plot_average_intensity.R: -------------------------------------------------------------------------------- 1 | #' plot_average_intensity 2 | #' 3 | #' @description Takes in a vector or radii and calculates the average intensity 4 | #' of a target marker using average_intensity function. It plots the intensity 5 | #' level as a line graph. 6 | #' 7 | #' @param spe_object SpatialExperiment object in the form of the output of 8 | #' \code{\link{format_image_to_spe}}. 9 | #' @param reference_marker String specifying the reference marker. 10 | #' @param target_marker String specifying the marker to calculate its average 11 | #' intensity. 12 | #' @param radii Numeric Vector specifying the search radius around reference 13 | #' cells. 14 | #' @import ggplot2 15 | #' @return A plot is returned 16 | #' @examples 17 | #' plot_average_intensity(SPIAT::simulated_image, reference_marker="Immune_marker3", 18 | #' target_marker="Immune_marker2", c(30, 35, 40, 45, 50, 75, 100)) 19 | #' @export 20 | 21 | plot_average_intensity <- function(spe_object, reference_marker, target_marker, radii) { 22 | 23 | average_intensity_result <- vector() 24 | 25 | for (radius in radii) { 26 | result <- average_marker_intensity_within_radius(spe_object, reference_marker, target_marker, radius = radius) 27 | #check 28 | if(!is.numeric(result)) { 29 | stop(sprintf("Cannot calculate average intensity for radius = %.2f", radius)) 30 | } 31 | average_intensity_result <- c(average_intensity_result, result) 32 | } 33 | 34 | average_intensity_df <- data.frame(radii, average_intensity_result) 35 | 36 | p <- ggplot(data=average_intensity_df, aes(x=radii, y=average_intensity_result)) 37 | 38 | title <- paste("Average intensity of ", target_marker, " from ", reference_marker, " for various radii", sep="") 39 | p <- p + geom_line() + geom_point() + ggtitle(title) + xlab("Radius") + ylab("Average Intensity") 40 | p <- p + theme_bw() 41 | p 42 | } 43 | -------------------------------------------------------------------------------- /R/plot_cell_distances_violin.R: -------------------------------------------------------------------------------- 1 | #' plot_cell_distances_violin 2 | #' 3 | #' @description Plots distances between cells as a violin plot 4 | #' 5 | #' @param cell_to_cell_dist Data.frame containing the distance output between cell types. The 6 | #' functions that generate the distances can be 7 | #' \code{\link{calculate_minimum_distances_between_celltypes}} and 8 | #' \code{\link{calculate_pairwise_distances_between_celltypes}}. 9 | #' @import ggplot2 10 | #' @examples 11 | #' distances <- calculate_pairwise_distances_between_celltypes(SPIAT::defined_image, 12 | #' cell_types_of_interest = c("Immune1", "Immune2"), feature_colname="Cell.Type") 13 | #' plot_cell_distances_violin(distances) 14 | #' @return A plot is returned 15 | #' @export 16 | 17 | 18 | plot_cell_distances_violin <- function(cell_to_cell_dist){ 19 | 20 | # setting these variables to NULL as otherwise get "no visible binding for global variable" in R check 21 | Pair <- Distance <- NULL 22 | 23 | ggplot(cell_to_cell_dist, aes(x = Pair, y = Distance)) + geom_violin() + 24 | facet_wrap(~Pair, scales="free_x") + 25 | theme_bw() 26 | 27 | } 28 | 29 | -------------------------------------------------------------------------------- /R/plot_cell_marker_levels.R: -------------------------------------------------------------------------------- 1 | #' plot_cell_marker_levels 2 | #' 3 | #' @description Produces a scatter plot of the level of a marker in each cell. 4 | #' The level of the marker in all cells is shown, at x-y positions, no matter 5 | #' if cells are phenotyped as being positive or negative for the particular 6 | #' marker. 7 | #' 8 | #' @param spe_object SpatialExperiment object in the form of the output of 9 | #' \code{\link{format_image_to_spe}}. 10 | #' @param marker String. Marker to plot. 11 | #' @param feature_colname String. Column containing marker information 12 | #' @import dplyr 13 | #' @import ggplot2 14 | #' @return A plot is returned 15 | #' @examples 16 | #' plot_cell_marker_levels(SPIAT::simulated_image, "Immune_marker1") 17 | #' @export 18 | 19 | plot_cell_marker_levels <- function(spe_object, marker, feature_colname = "Phenotype") { 20 | 21 | Cell.X.Position <- Cell.Y.Position <- NULL 22 | 23 | intensity_matrix <- SummarizedExperiment::assay(spe_object) 24 | markers <- rownames(intensity_matrix) 25 | 26 | #CHECK 27 | if (is.element(marker, markers) == FALSE) { 28 | stop("The marker specified is not in the data") 29 | } 30 | 31 | formatted_data <- bind_info(spe_object) 32 | 33 | #selecting cells that do not contain the marker 34 | #for one entry that is not marker 35 | rows <- formatted_data[formatted_data[[feature_colname]] != marker, ] 36 | #for multiple entries that does not contain marker 37 | rows <- rows[!grepl(marker, rows[[feature_colname]]), ] 38 | 39 | #for those cell without the marker, set marker intensity to 0 40 | #and merge the formatted_data 41 | rows[, marker] <- 0 42 | formatted_data[match(rows$Cell.ID,formatted_data$Cell.ID),]<-rows 43 | 44 | #selecting the cells that have intensity for a specific marker 45 | column <- which(colnames(formatted_data) == marker) 46 | rows_non_zero <- which(formatted_data[,column] != 0) 47 | intensity_by_marker <- formatted_data[rows_non_zero,] 48 | 49 | if (nrow(intensity_by_marker) == 0) { 50 | methods::show(paste("There are no true intensity for: ", marker, sep="")) 51 | } 52 | 53 | #log the intensity to improve contrast 54 | intensity_by_marker[,marker] <- log10(intensity_by_marker[,marker]) 55 | 56 | ggplot(intensity_by_marker, aes(x = Cell.X.Position, y = Cell.Y.Position, 57 | colour = eval(parse(text = marker)))) + 58 | geom_point(aes(colour=eval(parse(text = marker))),size = 0.1) + 59 | ggtitle(marker) + 60 | guides(alpha = "none") + scale_colour_viridis_c(direction = -1) + 61 | labs(colour = paste("log10","(", as.character(marker), 62 | " Intensity", ")",sep="")) + 63 | theme(panel.grid.major = element_blank(), 64 | panel.grid.minor = element_blank(), 65 | panel.background = element_rect(fill = "white"), 66 | axis.title.x = element_blank(), 67 | axis.text.x = element_blank(), 68 | axis.ticks.x = element_blank(), 69 | axis.title.y = element_blank(), 70 | axis.text.y = element_blank(), 71 | axis.ticks.y = element_blank()) 72 | } 73 | -------------------------------------------------------------------------------- /R/plot_cell_percentages.R: -------------------------------------------------------------------------------- 1 | #' plot_cell_percentages 2 | #' 3 | #' @description Plots cells proportions as barplots. 4 | #' @param cell_proportions Data Frame. Output from 5 | #' \code{\link{calculate_cell_proportions}}. 6 | #' @param cells_to_exclude String Vector. Markers to exclude. 7 | #' @param cellprop_colname String. Column to use for y axis names. Default is 8 | #' "Proportion_name". 9 | #' @import ggplot2 10 | #' @import dplyr 11 | #' @return A plot is returned 12 | #' @examples 13 | #' p_cells <- calculate_cell_proportions(SPIAT::simulated_image) 14 | #' plot_cell_percentages(p_cells) 15 | #' @export 16 | plot_cell_percentages <- function(cell_proportions, cells_to_exclude =NULL, 17 | cellprop_colname="Proportion_name"){ 18 | 19 | # setting these variables to NULL as otherwise get "no visible binding for global variable" in R check 20 | Cell_type <- Percentage <- Percentage_label <- NULL 21 | cellprop_colname <- rlang::ensym(cellprop_colname) 22 | 23 | cell_proportions$Percentage_label <- 24 | round(cell_proportions$Percentage, digits=1) 25 | cell_proportions <- cell_proportions[cell_proportions$Cell_type != "OTHER",] 26 | 27 | cell_percentages_full_plot <- 28 | ggplot(cell_proportions, 29 | aes(x = stats::reorder({{cellprop_colname}}, Percentage), 30 | y = Percentage, fill = Cell_type)) + 31 | geom_bar(stat = 'identity') + 32 | theme_bw() + 33 | theme() + 34 | xlab("Cell Type") + ylab("Proportion of cells") + 35 | geom_text(aes(label = Percentage_label), 36 | position = position_stack(vjust = 0.5),size = 3) + 37 | coord_flip() 38 | 39 | if(!is.null(cells_to_exclude)){ 40 | cell_proportions_no_tumour <- 41 | cell_proportions[!cell_proportions$Cell_type %in% cells_to_exclude,] 42 | cell_proportions_no_tumour$Proportion <- NULL 43 | cell_proportions_no_tumour$Percentage <- 44 | (cell_proportions_no_tumour$Number_of_celltype/ 45 | sum(cell_proportions_no_tumour$Number_of_celltype))*100 46 | cell_proportions_no_tumour$Percentage_label <- 47 | round(cell_proportions_no_tumour$Percentage, digits=1) 48 | 49 | cell_percentages_no_tumour_plot <- 50 | ggplot(cell_proportions_no_tumour, 51 | aes(x = stats::reorder({{cellprop_colname}}, Percentage), 52 | y = Percentage, fill=Cell_type)) + 53 | geom_bar(stat = 'identity') + 54 | ggtitle(paste("Excluding cells:",cells_to_exclude))+ 55 | theme_bw() + 56 | theme() + 57 | xlab("Cell Type") + ylab("Proportion of cells") + 58 | geom_text(aes(label = Percentage_label), 59 | position = position_stack(vjust = 0.5), size = 2) + 60 | coord_flip() 61 | return(cell_percentages_no_tumour_plot) 62 | # methods::show(cell_percentages_no_tumour_plot) 63 | }else return(cell_percentages_full_plot) 64 | # methods::show(cell_percentages_full_plot) 65 | } 66 | -------------------------------------------------------------------------------- /R/plot_composition_heatmap.R: -------------------------------------------------------------------------------- 1 | #' plot_composition_heatmap 2 | #' 3 | #' @description Produces a heatmap showing the marker percentages within each 4 | #' cluster and the cluster sizes. 5 | #' @param composition Data.frame. Output from 6 | #' \code{\link{composition_of_neighborhoods}}. 7 | #' @param pheno_to_exclude String Vector of phenotype to exclude. 8 | #' @param log_values Boolean. TRUE if the percentages should be logged (base 9 | #' 10). 10 | #' @param feature_colname String. Column with cell types. 11 | #' @return A plot is returned 12 | #' @examples 13 | #' neighborhoods <- identify_neighborhoods(image_no_markers, method = "hierarchical", 14 | #' min_neighborhood_size = 100, cell_types_of_interest = c("Immune", "Immune1", "Immune2"), 15 | #' radius = 50, feature_colname = "Cell.Type") 16 | #' neighborhoods_vis <- composition_of_neighborhoods(neighborhoods, feature_colname="Cell.Type") 17 | #' plot_composition_heatmap(neighborhoods_vis, feature_colname="Cell.Type") 18 | #' @export 19 | 20 | plot_composition_heatmap <- function(composition, pheno_to_exclude = NULL, 21 | log_values = FALSE, feature_colname) { 22 | cluster_size <- unique(data.frame( 23 | Neighborhood = composition$Neighborhood, 24 | Total_cells = composition$Total_number_of_cells)) 25 | rownames(cluster_size) <- cluster_size$Neighborhood 26 | cluster_size$Neighborhood <- NULL 27 | 28 | composition2 <- composition[,c(feature_colname, 29 | "Neighborhood", "Percentage")] 30 | composition2 <- reshape2::dcast(composition2, 31 | paste(feature_colname, "~", "Neighborhood"), 32 | value.var="Percentage") 33 | 34 | rownames(composition2) <- composition2[,feature_colname] 35 | composition2[,feature_colname] <- NULL 36 | composition2[is.na(composition2)] <- -1 37 | composition2 <- as.matrix(composition2) 38 | 39 | if(!is.null(pheno_to_exclude)){ 40 | composition2 <- composition2[!(rownames(composition2) %in% 41 | pheno_to_exclude),] 42 | } 43 | 44 | if(log_values){ 45 | composition2 <- apply(composition2, 2, log10) 46 | composition2[is.nan(composition2)] <- 1000 47 | composition2[composition2 == 1000] <- min(composition2)-1 48 | } 49 | 50 | #plot the heatmap 51 | map_cols <- grDevices::colorRampPalette(c("white", "red"))(1000) 52 | requireNamespace("ComplexHeatmap", quietly = TRUE) 53 | ha <- ComplexHeatmap::HeatmapAnnotation( 54 | "size" = ComplexHeatmap::anno_barplot(cluster_size), 55 | show_annotation_name = FALSE) 56 | ComplexHeatmap::Heatmap(as.matrix(composition2), name=" ", 57 | cluster_columns=TRUE, 58 | cluster_rows=TRUE, 59 | col = map_cols, 60 | top_annotation = ha, 61 | border = TRUE) 62 | 63 | } 64 | -------------------------------------------------------------------------------- /R/plot_distance_heatmap.R: -------------------------------------------------------------------------------- 1 | #' plot_distance_heatmap 2 | #' 3 | #' @description Takes the output of cell_distances and plot the distances as a 4 | #' heatmap. 5 | #' 6 | #' @param phenotype_distances_result Dataframe output from 7 | #' `calculate_summary_distances_between_celltypes` or 8 | #' `calculate_minimum_distances_between_celltypes`. 9 | #' @param metric Metric to be plotted. One of "mean", "std.dev", "median", "min" 10 | #' or "max". 11 | #' @import ggplot2 12 | #' @return A plot is returned 13 | #' @examples 14 | #' dists <- calculate_pairwise_distances_between_celltypes(SPIAT::defined_image, 15 | #' cell_types_of_interest = c("Tumour","Immune1"), feature_colname = "Cell.Type") 16 | #' summary_distances <- calculate_summary_distances_between_celltypes(dists) 17 | #' plot_distance_heatmap(summary_distances) 18 | #' @export 19 | 20 | plot_distance_heatmap <- function(phenotype_distances_result, metric = "mean"){ 21 | 22 | # setting these variables to NULL as otherwise get "no visible binding for global variable" in R check 23 | Reference <- Target <- Min <- Max <- Mean <- Std.Dev <- Median <- NULL 24 | 25 | if(metric == "mean"){ 26 | limit <- range(unlist(phenotype_distances_result$Mean), na.rm=TRUE) 27 | g <- ggplot(phenotype_distances_result, aes(x = Reference, y = Target, fill = Mean)) + 28 | geom_tile() + 29 | xlab("Reference cell type") + 30 | ylab("Target cell type") + 31 | theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank(), panel.background = element_rect(fill = "white"), 32 | axis.text.x = element_text(angle = 90, hjust = 1, vjust = 0.5)) + 33 | scale_fill_viridis_c(limits = limit, direction = -1) 34 | # methods::show(g) 35 | 36 | }else if(metric == "std.dev"){ 37 | limit <- range(unlist(phenotype_distances_result$Std.Dev), na.rm=TRUE) 38 | g <- ggplot(phenotype_distances_result, aes(x = Reference, y = Target, fill = Std.Dev)) + geom_tile() + 39 | xlab("Reference cell type") + ylab("Target cell type") + 40 | theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank(), panel.background = element_rect(fill = "white"), 41 | axis.text.x = element_text(angle = 90, hjust = 1, vjust = 0.5)) + 42 | scale_fill_viridis_c(limits = limit, direction = -1) 43 | # methods::show(g) 44 | 45 | }else if(metric == "median"){ 46 | limit <- range(unlist(phenotype_distances_result$Median), na.rm=TRUE) 47 | g <- ggplot(phenotype_distances_result, aes(x = Reference, y = Target, fill = Median)) + geom_tile() + 48 | xlab("Reference cell type") + ylab("Target cell type") + 49 | theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank(), panel.background = element_rect(fill = "white"), 50 | axis.text.x = element_text(angle = 90, hjust = 1, vjust = 0.5)) + 51 | scale_fill_viridis_c(limits = limit, direction = -1) 52 | # methods::show(g) 53 | }else if(metric == "min"){ 54 | limit <- range(unlist(phenotype_distances_result$Min), na.rm=TRUE) 55 | g <- ggplot(phenotype_distances_result, aes(x = Reference, y = Target, fill = Min)) + geom_tile() + 56 | xlab("Reference cell type") + ylab("Target cell type") + 57 | theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank(), panel.background = element_rect(fill = "white"), 58 | axis.text.x = element_text(angle = 90, hjust = 1, vjust = 0.5)) + 59 | scale_fill_viridis_c(limits = limit, direction = -1) 60 | # methods::show(g) 61 | }else if(metric == "max"){ 62 | limit <- range(unlist(phenotype_distances_result$Max), na.rm=TRUE) 63 | g <- ggplot(phenotype_distances_result, aes(x = Reference, y = Target, fill = Max)) + geom_tile() + 64 | xlab("Reference cell type") + ylab("Target cell type") + 65 | theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank(), panel.background = element_rect(fill = "white"), 66 | axis.text.x = element_text(angle = 90, hjust = 1, vjust = 0.5)) + 67 | scale_fill_viridis_c(limits = limit, direction = -1) 68 | # methods::show(g) 69 | } 70 | return(g) 71 | } 72 | -------------------------------------------------------------------------------- /R/plot_marker_level_heatmap.R: -------------------------------------------------------------------------------- 1 | #' plot_marker_level_heatmap 2 | #' 3 | #' @description Blurs the image by splitting the images into small squares. The 4 | #' marker levels are then averaged within each square. All cells are 5 | #' considered, regardless of phenotype status. 6 | #' 7 | #' @param spe_object SpatialExperiment object in the form of the output of 8 | #' \code{\link{format_image_to_spe}}. 9 | #' @param marker String. Marker to plot. 10 | #' @param num_splits Integer specifying the blurring level (number of splits) 11 | #' for the image. Higher numbers result in higher resolution. 12 | #' @import dplyr 13 | #' @import ggplot2 14 | #' @return A plot is returned 15 | #' @examples 16 | #' plot_marker_level_heatmap(SPIAT::simulated_image, num_splits = 100, "Tumour_marker") 17 | #' @export 18 | 19 | plot_marker_level_heatmap <- function(spe_object, num_splits, marker){ 20 | 21 | # setting these variables to NULL as otherwise get "no visible binding for global variable" in R check 22 | xcord <- ycord <- NULL 23 | 24 | formatted_data <- get_colData(spe_object) 25 | 26 | intensity_matrix <- SummarizedExperiment::assay(spe_object) 27 | 28 | markers <- rownames(intensity_matrix) 29 | 30 | #CHECK 31 | if (is.element(marker, markers) == FALSE) { 32 | stop("The marker specified is not in the data") 33 | } 34 | 35 | cell_ids <- colnames(intensity_matrix) 36 | 37 | rownames(intensity_matrix) <- NULL 38 | colnames(intensity_matrix) <- NULL 39 | intensity_matrix_t <- t(intensity_matrix) 40 | intensity_df <- data.frame(intensity_matrix_t) 41 | colnames(intensity_df) <- markers 42 | 43 | formatted_data <- cbind(formatted_data, intensity_df) 44 | formatted_data <- formatted_data[stats::complete.cases(formatted_data),] 45 | 46 | formatted_data$split.X <- 0 47 | formatted_data$split.Y <- 0 48 | 49 | minX <- min(formatted_data$Cell.X.Position, na.rm = TRUE) 50 | maxX <- max(formatted_data$Cell.X.Position, na.rm = TRUE) 51 | minY <- min(formatted_data$Cell.Y.Position, na.rm = TRUE) 52 | maxY <- max(formatted_data$Cell.Y.Position, na.rm = TRUE) 53 | 54 | #Splits the range of x and y coordinates 55 | #into n + 1 evenly spaced out lengths 56 | x_split <- seq(minX, maxX, length.out = num_splits + 1) 57 | y_split <- seq(minY, maxY, length.out = num_splits + 1) 58 | 59 | #Creates matrix of the locations of x and y cuts to the image 60 | split_occurrence <- cbind(x_split, y_split) 61 | 62 | #obtain the x and y coordinates on a heatmap for every cell based on number of splits 63 | for (y in seq_len(num_splits)){ 64 | local_coor_y <- y_split[c(y+1, y)] 65 | 66 | #grab the cells in the range 67 | result <- formatted_data[min(local_coor_y) < formatted_data$Cell.Y.Position & formatted_data$Cell.Y.Position <= max(local_coor_y), ] 68 | if(y == 1){ 69 | extra_row <- formatted_data[formatted_data$Cell.Y.Position == min(local_coor_y), ] 70 | result <- rbind(result, extra_row) 71 | } 72 | 73 | if(nrow(result) > 0) { 74 | result$split.Y <- y 75 | formatted_data[match(result$Cell.ID,formatted_data$Cell.ID),] <- result 76 | } 77 | } 78 | 79 | for (x in seq_len(num_splits)){ 80 | local_coor_x <- x_split[c(x+1, x)] 81 | 82 | #grab the cells in the range 83 | result <- formatted_data[min(local_coor_x) < formatted_data$Cell.X.Position & formatted_data$Cell.X.Position <= max(local_coor_x), ] 84 | if(x == 1){ 85 | extra_row <- formatted_data[formatted_data$Cell.X.Position == min(local_coor_x), ] 86 | result <- rbind(result, extra_row) 87 | } 88 | 89 | if(nrow(result) > 0) { 90 | result$split.X <- x 91 | formatted_data[match(result$Cell.ID,formatted_data$Cell.ID),] <- result 92 | } 93 | } 94 | 95 | heatmap_title <- paste(marker, "level") 96 | 97 | #create a df with only the intensity level of a single marker of interest and the coordinates 98 | df <- stats::aggregate(formatted_data[,marker], by=list(xcord=formatted_data$split.X, ycord=formatted_data$split.Y), FUN=mean) 99 | 100 | p <- ggplot(df, aes(xcord, ycord, fill=x)) + geom_tile() 101 | p <- p + scale_fill_gradient(low="white", high="red") 102 | p <- p + xlab("x position") + ylab("y position") 103 | p <- p + labs(fill = "Mean intensity level") + ggtitle(heatmap_title) 104 | p <- p + theme(panel.background = element_rect(fill = "grey", colour = "grey", linetype = "solid"), 105 | panel.grid.major = element_blank(), 106 | panel.grid.minor = element_blank()) 107 | # methods::show(p) 108 | return(p) 109 | } 110 | -------------------------------------------------------------------------------- /R/select_celltypes.R: -------------------------------------------------------------------------------- 1 | #' select_celltypes 2 | #' 3 | #' @description Select cell types to keep or exclude in the analysis. The output 4 | #' of this function also includes the original image size and cell count. 5 | #' 6 | #' @param spe_object SpatialExperiment object in the form of the output of 7 | #' \code{\link{format_image_to_spe}}. 8 | #' @param celltypes String Vector of celltypes of keep or exclude. 9 | #' @param feature_colname String. The column that has the interested cell types. 10 | #' If the cells ids are used to select cells, use "Cell.ID" for this arg. 11 | #' @param keep Boolean. TRUE if vector of `celltypes` are the cells that are 12 | #' going to be kept, FALSE if they are to be removed. 13 | #' @return A SpatialExperiment object is returned. The original image size 14 | #' and cell count can be accessed by `attr(slim_spe, "original_cell_number")` 15 | #' and `attr(slim_spe, "range_of_coords")`, where `slim_spe` is the output of 16 | #' this function. 17 | #' 18 | #' @examples 19 | #' data_subset <- select_celltypes(SPIAT::simulated_image, 20 | #' celltypes = c("Tumour_marker","Immune_marker1","Immune_marker2", 21 | #' "Immune_marker3","Immune_marker4"), 22 | #' feature_colname = "Phenotype", keep=TRUE) 23 | #' attr(data_subset, "original_cell_number") #cell number in the original image 24 | #' attr(data_subset, "range_of_coords") 25 | #' dim(data_subset)[2] # this is the new image cell number 26 | #' @export 27 | select_celltypes <- function(spe_object, celltypes, 28 | feature_colname = "Phenotype", keep = TRUE){ 29 | data <- get_colData(spe_object) 30 | 31 | # # if rownames have the cell types of interest, make rownames as a column 32 | if (feature_colname == "Cell.ID"){ 33 | SummarizedExperiment::colData(spe_object)$Cell.ID <- data$Cell.ID 34 | } 35 | 36 | # remember the total number of cells 37 | n_cells <- dim(data)[1] 38 | # remember the range of the cell coordinates 39 | xmax <- max(data$Cell.X.Position) 40 | xmin <- min(data$Cell.X.Position) 41 | ymax <- max(data$Cell.Y.Position) 42 | ymin <- min(data$Cell.Y.Position) 43 | 44 | # delete the cell rows 45 | if (keep) slim_spe <- 46 | spe_object[, (spe_object[[feature_colname]] %in% celltypes)] 47 | else slim_spe <- 48 | spe_object[, !(spe_object[[feature_colname]] %in% celltypes)] 49 | 50 | # # delete the rownames from the spe_object 51 | # SummarizedExperiment::colData(spe_object)$rownames <- NULL 52 | 53 | # save the original image info in the slim attr 54 | attr(slim_spe, "original_cell_number") <- n_cells 55 | attr(slim_spe, "range_of_coords") <- c(xmin = xmin, xmax = xmax, 56 | ymin = ymin, ymax = ymax) 57 | 58 | return(slim_spe) 59 | } 60 | -------------------------------------------------------------------------------- /R/simulated_image.R: -------------------------------------------------------------------------------- 1 | #' SPE object of a formatted image (simulated by `spaSim` package) 2 | #' 3 | #' A dataset that contains a formatted spe object with cell ids and phenotypes 4 | #' in `colData()` and marker intensities in `assays()`. 5 | #' 6 | #' @format An SpatialExperiment object. Assay contains 5 rows (markers) and 4951 7 | #' columns (cells); colData contains 4951 rows (cells) and 3 columns. 8 | #' @seealso \code{\link{defined_image}} \code{\link{image_no_markers}} 9 | "simulated_image" 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SPIAT - Spatial Image Analysis of Tissues 2 | 3 | SPIAT (Spatial Image Analysis of Tissues) is an R package with a suite of data processing, quality control, visualization, data handling and data analysis tools. SPIAT is compatible with data generated from single-cell spatial proteomics platforms (e.g. OPAL, CODEX, MIBI). SPIAT reads spatial data in the form of X and Y coordinates of cells, marker intensities and cell phenotypes. 4 | 5 | SPIAT includes six analysis modules that allow visualization, calculation of cell colocalization, categorization of the immune microenvironment relative to tumor areas, analysis of cellular neighborhoods, and the quantification of spatial heterogeneity, providing a comprehensive toolkit for spatial data analysis. 6 | 7 | 8 | ## Installation 9 | 10 | To install this package, start R and enter: 11 | ```r 12 | if (!require("BiocManager", quietly = TRUE)) 13 | install.packages("BiocManager") 14 | BiocManager::install("SPIAT") 15 | ``` 16 | You can also install the latest development version from Github. 17 | 18 | ```r 19 | if (!requireNamespace("devtools", quietly = TRUE)) { 20 | install.packages("devtools")} 21 | devtools::install_github("TrigosTeam/SPIAT") 22 | ``` 23 | The estimated installation time on a Windows 10 (64-bit) system is 1.5 minutes. 24 | 25 | ## Vignette 26 | 27 | The vignette with an overview of the package can be accessed from the top Menu under Articles or by clicking [here](https://trigosteam.github.io/SPIAT/articles/SPIAT.html). 28 | 29 | ## Issues 30 | 31 | Please open an issue on our Github page (https://github.com/TrigosTeam/SPIAT/issues) if you have any questions. 32 | 33 | ## Authors of the package 34 | Yuzhou Feng, Tianpei Yang, Volkan Ozcoban, Mabel Li and John Zhu developed the package, including developing algorithms, writing code and designing the package. Yuzhou Feng and Maria Doyle did the package cleaning and wrote the tutorial. Anna Trigos conceived, supervised the work, developed algorithms and designed the package. 35 | 36 | ## Paper reference 37 | Please check our latest paper for more information! 38 | 39 | Yuzhou Feng et al, Spatial analysis with SPIAT and spaSim to characterize and simulate tissue microenvironments, Nature Communications (2023). DOI: 10.1038/s41467-023-37822-0 40 | -------------------------------------------------------------------------------- /data-raw/defined_image.R: -------------------------------------------------------------------------------- 1 | ## code to prepare `defined_image` dataset goes here 2 | ##### 3 | categories <- c("Tumour_marker", "Immune_marker1,Immune_marker2", 4 | "Immune_marker1,Immune_marker3", 5 | "Immune_marker1,Immune_marker2,Immune_marker4", "OTHER") 6 | names <- c("Tumour", "Immune1", "Immune2", "Immune3", "Others") 7 | 8 | defined_image <- define_celltypes(SPIAT::simulated_image, categories, 9 | category_colname = "Phenotype", 10 | names, new_colname = "Cell.Type") 11 | ##### 12 | usethis::use_data(defined_image, overwrite = TRUE) 13 | -------------------------------------------------------------------------------- /data-raw/image_no_markers.R: -------------------------------------------------------------------------------- 1 | ## code to prepare `image_no_markers` dataset goes here 2 | ##### 3 | library(spaSim) 4 | library(SPIAT) 5 | 6 | # simulate an image with three immune clusters 7 | set.seed(610) 8 | bg <- simulate_mixing(idents = c("Tumour", "Immune1", "Immune2", 9 | "Immune", "Others"), 10 | props =c(0.03, 0.1, 0.05, 0.02, 0.8), 11 | plot_image = FALSE) 12 | 13 | set.seed(610) 14 | a <- simulate_clusters(bg_sample = bg, 15 | n_clusters = 4, cluster_properties = list( 16 | C1 = list(name_of_cluster_cell = "Immune1", size = 900, 17 | shape = "Irregular", centre_loc = data.frame(x = 200, y = 200), 18 | infiltration_types = c("Immune","Immune2", "Others"), 19 | infiltration_proportions = c(0.3, 0.2, 0.1)), 20 | C2 = list(name_of_cluster_cell = "Immune2", size = 1000, 21 | shape = "Irregular", centre_loc = data.frame(x = 1200, y = 400), 22 | infiltration_types = c("Immune", "Others"), 23 | infiltration_proportions = c(0.2, 0.05)), 24 | C3 = list(name_of_cluster_cell = "Immune", size = 800, 25 | shape = "Irregular", centre_loc = data.frame(x = 500, y = 1200), 26 | infiltration_types = c("Immune1", "Immune2", "Others"), 27 | infiltration_proportions = c(0.2, 0.3, 0.05)), 28 | C4 = list(name_of_cluster_cell = "Immune", size = 280, 29 | shape = "Oval", centre_loc = data.frame(x = 800, y = 1200), 30 | infiltration_types = c("Immune1", "Immune2", "Others"), 31 | infiltration_proportions = c(0.2, 0.3, 0.05))), 32 | plot_image = FALSE) 33 | 34 | plot_cell_categories(a, c("Tumour","Immune1", "Immune2", "Immune"), 35 | c("red","darkblue", "darkgreen", "brown"), "Cell.Type") 36 | 37 | 38 | table(a$Cell.Type) 39 | # Immune Immune1 Immune2 Others Tumour 40 | # 499 600 674 3059 119 41 | sum(table(a$Cell.Type)) 42 | 43 | 44 | # simulate cell sizes 45 | set.seed(610) 46 | Tumour_size <- rnorm(119, 15, 2) 47 | plot(density(Tumour_size)) 48 | a[a$Cell.Type == "Tumour", "Cell.Size"] <- Tumour_size 49 | 50 | set.seed(610) 51 | Immune_size <- rnorm(1773, 9, 3) 52 | plot(density(Immune_size)) 53 | a[a$Cell.Type %in% c("Immune","Immune1","Immune2"), "Cell.Size"] <- Immune_size 54 | 55 | set.seed(610) 56 | Other_size <- rnorm(3059, 12, 6) 57 | plot(density(Other_size)) 58 | a[a$Cell.Type == "Others", "Cell.Size"] <- Other_size 59 | 60 | # format to spe 61 | intensity_matrix <- NULL 62 | coord_x <- a$Cell.X.Position 63 | coord_y <- a$Cell.Y.Position 64 | 65 | image_no_markers <- format_colData_to_spe(a) 66 | plot_cell_categories(image_no_markers, c("Tumour","Immune1", "Immune2", "Immune"), 67 | c("red","darkblue", "darkgreen", "brown"), "Cell.Type") 68 | ##### 69 | usethis::use_data(image_no_markers, overwrite = TRUE) 70 | -------------------------------------------------------------------------------- /data/defined_image.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TrigosTeam/SPIAT/f649d7942abb70fee8c6f630b725033bc5c9524b/data/defined_image.rda -------------------------------------------------------------------------------- /data/image_no_markers.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TrigosTeam/SPIAT/f649d7942abb70fee8c6f630b725033bc5c9524b/data/image_no_markers.rda -------------------------------------------------------------------------------- /data/simulated_image.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TrigosTeam/SPIAT/f649d7942abb70fee8c6f630b725033bc5c9524b/data/simulated_image.rda -------------------------------------------------------------------------------- /inst/CITATION: -------------------------------------------------------------------------------- 1 | c( 2 | bibentry( 3 | bibtype = "manual", 4 | title = "SPIAT: Spatial Image Analysis of Cells in Tissues", 5 | author =c( 6 | person("Anna S", "Trigos"), 7 | person("Yuzhou", "Feng"), 8 | person("Tianpei", "Yang"), 9 | person("Mabel" , "Li"), 10 | person("John", "Zhu"), 11 | person("Volkan", "Ozcoban"), 12 | person("Maria", "Doyle") 13 | ), 14 | note = "R package version 1.9.1", 15 | year = "2025", 16 | url = "https://trigosteam.github.io/SPIAT/"), 17 | bibentry( 18 | bibtype = "article", 19 | title = "Spatial analysis with SPIAT and spaSim to characterize and simulate tissue microenvironments", 20 | author =c( 21 | person("Yuzhou", "Feng"), 22 | person("Tianpei", "Yang"), 23 | person("John", "Zhu"), 24 | person("Mabel", "Li"), 25 | person("Maria", "Doyle"), 26 | person("Volkan", "Ozcoban"), 27 | person("Greg T", "Bass"), 28 | person("Angela", "Pizzolla"), 29 | person("Lachlan", "Cain"), 30 | person("Sirui", "Weng"), 31 | person("Anupama", "Pasam"), 32 | person("Nikolce", "Kocovski"), 33 | person("Yu-Kuan", "Huang"), 34 | person("Simon P", "Keam"), 35 | person("Terence P", "Speed"), 36 | person("Paul J", "Neeson"), 37 | person("Richard B", "Pearson"), 38 | person("Shahneen K", "Sandhu"), 39 | person("David L", "Goode"), 40 | person("Anna S", "Trigos") 41 | ), 42 | journal = "Nature Communications", 43 | volume = "14", 44 | number = "2697", 45 | year = "2023", 46 | doi = "10.1038/s41467-023-37822-0")) 47 | 48 | -------------------------------------------------------------------------------- /inst/extdata/tiny_cellprofiler.txt.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TrigosTeam/SPIAT/f649d7942abb70fee8c6f630b725033bc5c9524b/inst/extdata/tiny_cellprofiler.txt.gz -------------------------------------------------------------------------------- /inst/extdata/tiny_codex.csv.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TrigosTeam/SPIAT/f649d7942abb70fee8c6f630b725033bc5c9524b/inst/extdata/tiny_codex.csv.gz -------------------------------------------------------------------------------- /inst/extdata/tiny_codex_phenotypes.txt.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TrigosTeam/SPIAT/f649d7942abb70fee8c6f630b725033bc5c9524b/inst/extdata/tiny_codex_phenotypes.txt.gz -------------------------------------------------------------------------------- /inst/extdata/tiny_halo.csv.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TrigosTeam/SPIAT/f649d7942abb70fee8c6f630b725033bc5c9524b/inst/extdata/tiny_halo.csv.gz -------------------------------------------------------------------------------- /inst/extdata/tiny_inform.txt.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TrigosTeam/SPIAT/f649d7942abb70fee8c6f630b725033bc5c9524b/inst/extdata/tiny_inform.txt.gz -------------------------------------------------------------------------------- /inst/vignettes/introduction.bib: -------------------------------------------------------------------------------- 1 | @article{keren2018structured, 2 | title={A structured tumor-immune microenvironment in triple negative breast cancer revealed by multiplexed ion beam imaging}, 3 | author={Keren, Leeat and Bosse, Marc and Marquez, Diana and Angoshtari, Roshan and Jain, Samir and Varma, Sushama and Yang, Soo-Ryum and Kurian, Allison and Van Valen, David and West, Robert and others}, 4 | journal={Cell}, 5 | volume={174}, 6 | number={6}, 7 | pages={1373--1387}, 8 | year={2018}, 9 | publisher={Elsevier} 10 | } 11 | 12 | @article{jackson2020single, 13 | title={The single-cell pathology landscape of breast cancer}, 14 | author={Jackson, Hartland W and Fischer, Jana R and Zanotelli, Vito RT and Ali, H Raza and Mechera, Robert and Soysal, Savas D and Moch, Holger and Muenst, Simone and Varga, Zsuzsanna and Weber, Walter P and others}, 15 | journal={Nature}, 16 | volume={578}, 17 | number={7796}, 18 | pages={615--620}, 19 | year={2020}, 20 | publisher={Nature Publishing Group} 21 | } 22 | 23 | @article{hahsler2019dbscan, 24 | title={dbscan: Fast density-based clustering with r}, 25 | author={Hahsler, Michael and Piekenbrock, Matthew and Doran, Derek}, 26 | journal={Journal of Statistical Software}, 27 | volume={91}, 28 | number={1}, 29 | pages={1--30}, 30 | year={2019}, 31 | publisher={Springer-Verlag} 32 | } 33 | 34 | @article{yang2020spiat, 35 | title={SPIAT: An R package for the Spatial Image Analysis of Cells in Tissues}, 36 | author={Yang, Tianpei and Ozcoban, Volkan and Pasam, Anu and Kocovski, Nikolce and Pizzolla, Angela and Huang, Yu-Kuan and Bass, Greg and Keam, Simon P and Neeson, Paul J and Sandhu, Shahneen K and others}, 37 | journal={bioRxiv}, 38 | year={2020}, 39 | publisher={Cold Spring Harbor Laboratory} 40 | } 41 | 42 | @Manual{alphahull, 43 | title = {alphahull: Generalization of the Convex Hull of a Sample of Points in the 44 | Plane}, 45 | author = {Beatriz Pateiro-Lopez and Alberto Rodriguez-Casal and {.}}, 46 | year = {2019}, 47 | note = {R package version 2.2}, 48 | url = {https://CRAN.R-project.org/package=alphahull}, 49 | } 50 | -------------------------------------------------------------------------------- /man/AUC_of_cross_function.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/AUC_of_cross_function.R 3 | \name{AUC_of_cross_function} 4 | \alias{AUC_of_cross_function} 5 | \title{The difference in AUC of the cross function curves} 6 | \usage{ 7 | AUC_of_cross_function(df.cross) 8 | } 9 | \arguments{ 10 | \item{df.cross}{Data.frame. The output of 11 | \code{\link{calculate_cross_functions}}. Containing the positions of the 12 | two curves. Columns contain "r", "border" and "theo".} 13 | } 14 | \value{ 15 | A number 16 | } 17 | \description{ 18 | Calculate the difference of area under the curve (AUC) between 19 | two curves, normalised by the total area of the graph. 20 | } 21 | \examples{ 22 | df_cross <- calculate_cross_functions(SPIAT::defined_image, method = "Kcross", 23 | cell_types_of_interest = c("Tumour","Immune3"), 24 | feature_colname ="Cell.Type", dist = 100) 25 | AUC_of_cross_function(df_cross) 26 | } 27 | -------------------------------------------------------------------------------- /man/R_BC.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/R_BC.R 3 | \name{R_BC} 4 | \alias{R_BC} 5 | \title{The ratio of border cell count to cluster cell count} 6 | \usage{ 7 | R_BC(spe_object, cell_type_of_interest, feature_colname) 8 | } 9 | \arguments{ 10 | \item{spe_object}{SpatialExperiment object in the form of the output of 11 | \code{\link{format_image_to_spe}}.} 12 | 13 | \item{cell_type_of_interest}{String. The cell type that the user wants to 14 | determine a cluster of.} 15 | 16 | \item{feature_colname}{String. The column that contains the cell type to be clustered.} 17 | } 18 | \value{ 19 | A number is returned. 20 | } 21 | \description{ 22 | Calculates the ratio of the bordering cell count and the 23 | total to-be-clustered cell count in an image. The bordering cells are detected 24 | by the default \code{\link{identify_bordering_cells}} function. If the 25 | ratio is high, it means that most cells to be clustered are identified as bordering 26 | cells. This means there is no clear clusters. 27 | } 28 | \examples{ 29 | R_BC(SPIAT::defined_image, cell_type_of_interest = "Tumour", "Cell.Type") 30 | 31 | } 32 | -------------------------------------------------------------------------------- /man/SPIAT-package.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/SPIAT-package.R 3 | \docType{package} 4 | \name{SPIAT-package} 5 | \alias{SPIAT} 6 | \alias{SPIAT-package} 7 | \title{SPIAT: Spatial Image Analysis of Tissues} 8 | \description{ 9 | SPIAT (**Sp**atial **I**mage **A**nalysis of **T**issues) is an R package with a suite of data processing, quality control, visualization and data analysis tools. SPIAT is compatible with data generated from single-cell spatial proteomics platforms (e.g. OPAL, CODEX, MIBI, cellprofiler). SPIAT reads spatial data in the form of X and Y coordinates of cells, marker intensities and cell phenotypes. SPIAT includes six analysis modules that allow visualization, calculation of cell colocalization, categorization of the immune microenvironment relative to tumor areas, analysis of cellular neighborhoods, and the quantification of spatial heterogeneity, providing a comprehensive toolkit for spatial data analysis. 10 | } 11 | \seealso{ 12 | Useful links: 13 | \itemize{ 14 | \item \url{https://trigosteam.github.io/SPIAT/} 15 | \item Report bugs at \url{https://github.com/trigosteam/SPIAT/issues} 16 | } 17 | 18 | } 19 | \author{ 20 | \strong{Maintainer}: Yuzhou Feng \email{yuzhou.feng@petermac.org} (\href{https://orcid.org/0000-0002-2955-4053}{ORCID}) 21 | 22 | Authors: 23 | \itemize{ 24 | \item Anna Trigos \email{anna.trigos@petermac.org} (\href{https://orcid.org/0000-0002-5915-2952}{ORCID}) 25 | \item Tianpei Yang \email{yangtp3344@gmail.com} 26 | \item Mabel Li 27 | \item John Zhu 28 | \item Volkan Ozcoban \email{volkanozcoban1@gmail.com} 29 | \item Maria Doyle \email{maria.doyle@petermac.org} 30 | } 31 | 32 | } 33 | \keyword{internal} 34 | -------------------------------------------------------------------------------- /man/average_marker_intensity_within_radius.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/average_marker_intensity_within_radius.R 3 | \name{average_marker_intensity_within_radius} 4 | \alias{average_marker_intensity_within_radius} 5 | \title{average_marker_intensity_within_radius} 6 | \usage{ 7 | average_marker_intensity_within_radius( 8 | spe_object, 9 | reference_marker, 10 | target_marker, 11 | radius = 20 12 | ) 13 | } 14 | \arguments{ 15 | \item{spe_object}{SpatialExperiment object in the form of the output of 16 | \code{\link{format_image_to_spe}}.} 17 | 18 | \item{reference_marker}{String specifying the marker that is used for 19 | reference cells.} 20 | 21 | \item{target_marker}{String specifying the marker to calculate its average 22 | intensity.} 23 | 24 | \item{radius}{Numeric specifying the radius of search for cells around the 25 | reference cells.} 26 | } 27 | \value{ 28 | A single number is returned 29 | } 30 | \description{ 31 | Calculates the average intensity of the target_marker within a 32 | radius from the cells positive for the reference marker. Note that it pools 33 | all cells with the target marker that are within the specific radius of any 34 | reference cell. Results represent the average intensities within a radius, 35 | but not a vector of metrics for each cell. 36 | } 37 | \examples{ 38 | average_marker_intensity_within_radius(SPIAT::simulated_image, 39 | reference_marker ="Immune_marker3", 40 | target_marker = "Immune_marker2", 41 | radius=30) 42 | } 43 | -------------------------------------------------------------------------------- /man/average_minimum_distance.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/average_minimum_distance.R 3 | \name{average_minimum_distance} 4 | \alias{average_minimum_distance} 5 | \title{average_minimum_distance} 6 | \usage{ 7 | average_minimum_distance(spe_object) 8 | } 9 | \arguments{ 10 | \item{spe_object}{SpatialExperiment object in the form of the output of 11 | \code{\link{format_image_to_spe}}.} 12 | } 13 | \value{ 14 | A single number is returned 15 | } 16 | \description{ 17 | Calculates the average minimum distance of all cells to their 18 | nearest cells in the input image. 19 | } 20 | \examples{ 21 | average_minimum_distance(SPIAT::simulated_image) 22 | } 23 | -------------------------------------------------------------------------------- /man/average_nearest_neighbor_index.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/average_nearest_neighbor_index.R 3 | \name{average_nearest_neighbor_index} 4 | \alias{average_nearest_neighbor_index} 5 | \title{Average nearest neighbor index for point pattern (clustering or dispersion)} 6 | \usage{ 7 | average_nearest_neighbor_index( 8 | spe_object, 9 | reference_celltypes, 10 | feature_colname, 11 | p_val = 5e-06 12 | ) 13 | } 14 | \arguments{ 15 | \item{spe_object}{SpatialExperiment object in the form of the output of 16 | \code{\link{format_image_to_spe}}.} 17 | 18 | \item{reference_celltypes}{String Vector. Cells with these cell types will be 19 | used for ANNI calculation.} 20 | 21 | \item{feature_colname}{String. Specify the selected column for 22 | `reference_celltypes`.} 23 | 24 | \item{p_val}{Numeric. The p value threshold to determine the significance of 25 | a pattern.} 26 | } 27 | \value{ 28 | A list with the ANN index, the pattern type and the corresponding p 29 | value 30 | } 31 | \description{ 32 | Calculate the the average nearest neighbor (ANN) index of a 33 | specified type of cells. The index indicates the clustering effect of a 34 | point pattern. The pattern can be clustering, random or dispersion. 35 | } 36 | \details{ 37 | ANN index is a statistical test to test for the presence of clusters 38 | of cells, (Clark and Evans, 1954). The ANN index evaluates the spatial 39 | aggregation or dispersion effect of objects based on the average distances 40 | between pairs of the nearest objects and can be used to test for the 41 | clustering of specific cell types (e.g. immune or tumor cells). Next, the z 42 | score and p-value of the ANN index is calculated to validate the 43 | significance of the pattern. 44 | } 45 | \examples{ 46 | average_nearest_neighbor_index(SPIAT::defined_image, reference_celltypes = 47 | "Tumour", feature_colname = "Cell.Type") 48 | } 49 | -------------------------------------------------------------------------------- /man/average_percentage_of_cells_within_radius.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/average_percentage_of_cells_within_radius.R 3 | \name{average_percentage_of_cells_within_radius} 4 | \alias{average_percentage_of_cells_within_radius} 5 | \title{average_percentage_of_cells_within_radius} 6 | \usage{ 7 | average_percentage_of_cells_within_radius( 8 | spe_object, 9 | reference_celltype, 10 | target_celltype, 11 | radius = 100, 12 | feature_colname 13 | ) 14 | } 15 | \arguments{ 16 | \item{spe_object}{SpatialExperiment object in the form of the output of 17 | \code{\link{format_image_to_spe}}.} 18 | 19 | \item{reference_celltype}{String specifying the cell type of reference 20 | cells.} 21 | 22 | \item{target_celltype}{String specifying the cell type for target cells} 23 | 24 | \item{radius}{Integer specifying the radius of search for cells around the 25 | reference cells. Radii of ~100 are recommended. If too small, too few cells 26 | might be present.} 27 | 28 | \item{feature_colname}{String specifying the column with the desired cell 29 | type annotations.} 30 | } 31 | \value{ 32 | A numeric vector and a plot are returned 33 | } 34 | \description{ 35 | Calculates the average percentage of cells of a target cell type 36 | within a radius from the cells with a reference cell type. The calculation 37 | is done per reference cell, so runtime will depend on the number of 38 | reference cells present. Output is a single value (the mean for the image). 39 | } 40 | \examples{ 41 | average_percentage_of_cells_within_radius(SPIAT::defined_image, "Tumour", 42 | "Immune3", radius = 100, "Cell.Type") 43 | } 44 | -------------------------------------------------------------------------------- /man/calculate_cell_proportions.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/calculate_cell_proportions.R 3 | \name{calculate_cell_proportions} 4 | \alias{calculate_cell_proportions} 5 | \title{calculate_cell_proportions} 6 | \usage{ 7 | calculate_cell_proportions( 8 | spe_object, 9 | reference_celltypes = NULL, 10 | celltypes_to_exclude = NULL, 11 | feature_colname = "Phenotype", 12 | plot.image = TRUE 13 | ) 14 | } 15 | \arguments{ 16 | \item{spe_object}{SpatialExperiment object in the form of the output of 17 | \code{\link{format_image_to_spe}}.} 18 | 19 | \item{reference_celltypes}{String Vector specifying reference cell types. If 20 | NULL (default), then the proportion of each cell type against all cells is 21 | returned. Alternatively, a custom vector of cell types can be used as 22 | input, and these will be used as the denominator in the calculation of the 23 | proportions.} 24 | 25 | \item{celltypes_to_exclude}{String Vector specifying cell types to exclude. 26 | For example "OTHER" will exclude that celltype from the Total. If NULL, all 27 | cell types are included.} 28 | 29 | \item{feature_colname}{String. Column of cells to choose the cell type from 30 | (e.g. Phenotype, Cell.Type, etc).} 31 | 32 | \item{plot.image}{Boolean. Whether to plot the barplot of the cell percentages. 33 | By default is TRUE.} 34 | } 35 | \value{ 36 | A data.frame is returned 37 | } 38 | \description{ 39 | Calculates the number and proportion of each cell type. 40 | } 41 | \examples{ 42 | calculate_cell_proportions(SPIAT::defined_image, reference_celltypes = NULL, 43 | celltypes_to_exclude = "Others", feature_colname="Cell.Type", plot.image = FALSE) 44 | } 45 | -------------------------------------------------------------------------------- /man/calculate_cross_functions.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/calculate_cross_functions.R 3 | \name{calculate_cross_functions} 4 | \alias{calculate_cross_functions} 5 | \title{calculate_cross_functions} 6 | \usage{ 7 | calculate_cross_functions( 8 | spe_object, 9 | method = "Kcross", 10 | cell_types_of_interest, 11 | feature_colname, 12 | plot_results = TRUE, 13 | dist = NULL 14 | ) 15 | } 16 | \arguments{ 17 | \item{spe_object}{SpatialExperiment object in the form of the output of 18 | \code{\link{format_image_to_spe}}.} 19 | 20 | \item{method}{String that is the method for dependence calculation. Options: 21 | "Gcross", "Kcross", "Kcross.inhom", "Lcross", "Jcross". Default method is 22 | "Kcross".} 23 | 24 | \item{cell_types_of_interest}{String Vector. Cell types of interest.} 25 | 26 | \item{feature_colname}{String that is the name of the column of the types.} 27 | 28 | \item{plot_results}{Boolean. TRUE if result to be plotted, FALSE if not. In 29 | either case, an object with the results is returned} 30 | 31 | \item{dist}{Number (OPTIONAL) The largest distance between two cell types at 32 | which K function is evaluated. If NULL, use the default distances set by 33 | cross functions.} 34 | } 35 | \value{ 36 | An object of class "fv" defined in `spatstat` package. 37 | } 38 | \description{ 39 | Compute and plot the cross functions between two specified cell 40 | types. This function implements the cross functions from [spatstat] package. 41 | } 42 | \examples{ 43 | df_cross <- calculate_cross_functions(SPIAT::defined_image, 44 | method = "Kcross", cell_types_of_interest = c("Tumour","Immune3"), 45 | feature_colname ="Cell.Type", dist = 100) 46 | } 47 | -------------------------------------------------------------------------------- /man/calculate_distance_to_margin.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/calculate_distance_to_tumour_margin.R 3 | \name{calculate_distance_to_margin} 4 | \alias{calculate_distance_to_margin} 5 | \title{calculate the distances of each cell to the margin} 6 | \usage{ 7 | calculate_distance_to_margin(spe_object) 8 | } 9 | \arguments{ 10 | \item{spe_object}{SpatialExperiment object. It should contain information of 11 | the detected bordering cells (`colData()` has `Region` column).} 12 | } 13 | \value{ 14 | An spe_object with a `Distance.To.Border` column is returned. 15 | } 16 | \description{ 17 | Returns a SPE object with the minimum distance from cells of 18 | interest (CoI) to the identified bordering cells. 19 | } 20 | \examples{ 21 | spe_border <- identify_bordering_cells(SPIAT::defined_image, 22 | reference_cell = "Tumour", feature_colname = "Cell.Type", n_to_exclude = 10) 23 | spe_dist <- calculate_distance_to_margin(spe_border) 24 | } 25 | -------------------------------------------------------------------------------- /man/calculate_entropy.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/calculate_entropy.R 3 | \name{calculate_entropy} 4 | \alias{calculate_entropy} 5 | \title{calculate_entropy} 6 | \usage{ 7 | calculate_entropy( 8 | spe_object, 9 | cell_types_of_interest, 10 | feature_colname = "Phenotype", 11 | radius = NULL 12 | ) 13 | } 14 | \arguments{ 15 | \item{spe_object}{SpatialExperiment object in the form of the output of 16 | \code{\link{format_image_to_spe}}.} 17 | 18 | \item{cell_types_of_interest}{String Vector. Cell types of interest. If arg 19 | `radius` is not NULL, the first cell type is considered as reference cell 20 | type. Circles of the specified radius will be drawn around the reference 21 | cells and the entropy of cell types will be calculated for each of the 22 | reference cells.} 23 | 24 | \item{feature_colname}{String specifying the column the cell types are from.} 25 | 26 | \item{radius}{(OPTIONAL) Numeric. The maximum radius around a reference cell 27 | for another cell to be considered an interaction.} 28 | } 29 | \value{ 30 | A dataframe or a number depending on the argument radius 31 | } 32 | \description{ 33 | If arg `radius` is not specified, the function returns the 34 | entropy of the cell types of interest for the whole image. If arg `radius` 35 | is specified, the function returns a data frame where each row is a 36 | reference cell and the columns stores the entropy of the cell types of 37 | interest in each circle of the reference cells. 38 | } 39 | \examples{ 40 | calculate_entropy(SPIAT::defined_image, 41 | cell_types_of_interest = c("Immune1","Immune2"), 42 | feature_colname = "Cell.Type") 43 | } 44 | -------------------------------------------------------------------------------- /man/calculate_minimum_distances_between_celltypes.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/calculate_minimum_distances_between_celltypes.R 3 | \name{calculate_minimum_distances_between_celltypes} 4 | \alias{calculate_minimum_distances_between_celltypes} 5 | \title{calculate_minimum_distances_between_celltypes} 6 | \usage{ 7 | calculate_minimum_distances_between_celltypes( 8 | spe_object, 9 | feature_colname, 10 | cell_types_of_interest = NULL 11 | ) 12 | } 13 | \arguments{ 14 | \item{spe_object}{SpatialExperiment object in the form of the output of 15 | \code{\link{format_image_to_spe}}.} 16 | 17 | \item{feature_colname}{String of the feature column of cells to choose the 18 | cell types from (e.g. Cell.Type, Cell.Type2, etc).} 19 | 20 | \item{cell_types_of_interest}{String Vector of marker combinations to 21 | consider is FALSE.} 22 | } 23 | \value{ 24 | A data.frame is returned 25 | } 26 | \description{ 27 | Returns the distance of the closest cell of a specific type from 28 | each reference cell. 29 | } 30 | \examples{ 31 | min_dists <- calculate_minimum_distances_between_celltypes( 32 | SPIAT::defined_image, feature_colname = "Cell.Type", 33 | cell_types_of_interest = c("Tumour","Immune1")) 34 | } 35 | -------------------------------------------------------------------------------- /man/calculate_pairwise_distances_between_celltypes.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in 3 | % R/calculate_pairwise_distances_between_celltypes.R 4 | \name{calculate_pairwise_distances_between_celltypes} 5 | \alias{calculate_pairwise_distances_between_celltypes} 6 | \title{calculate_pairwise_distances_between_celltypes} 7 | \usage{ 8 | calculate_pairwise_distances_between_celltypes( 9 | spe_object, 10 | cell_types_of_interest = NULL, 11 | feature_colname 12 | ) 13 | } 14 | \arguments{ 15 | \item{spe_object}{SpatialExperiment object in the form of the output of 16 | \code{\link{format_image_to_spe}}.} 17 | 18 | \item{cell_types_of_interest}{String Vector containing cell types to be 19 | considered, if NULL, all cell type combinations will be calculated.} 20 | 21 | \item{feature_colname}{String of the name the feature column with the cell 22 | types of interest to be considered.} 23 | } 24 | \value{ 25 | A data.frame is returned. 26 | } 27 | \description{ 28 | Returns the pairwise distances between cells of different types. 29 | If none of the cell types are found, it will print an error message and 30 | return a vector of NAs. 31 | } 32 | \examples{ 33 | calculate_pairwise_distances_between_celltypes(SPIAT::defined_image, 34 | cell_types_of_interest = c("Tumour","Immune1"), 35 | feature_colname = "Cell.Type") 36 | } 37 | -------------------------------------------------------------------------------- /man/calculate_percentage_of_grids.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/calculate_percentage_of_grids.R 3 | \name{calculate_percentage_of_grids} 4 | \alias{calculate_percentage_of_grids} 5 | \title{calculate_percentage_of_grids} 6 | \usage{ 7 | calculate_percentage_of_grids(raster_obj, threshold, above) 8 | } 9 | \arguments{ 10 | \item{raster_obj}{Raster object in the form of the output of 11 | \code{\link{grid_metrics}}.} 12 | 13 | \item{threshold}{Numeric. The threshold for defining the pattern.} 14 | 15 | \item{above}{Boolean. Indicating whether the pattern is above (TRUE) or below 16 | (FALSE) the threshold.} 17 | } 18 | \value{ 19 | A number is returned 20 | } 21 | \description{ 22 | Takes the result of \code{\link{grid_metrics}} (a RasterLayer 23 | object) and calculates the percentage of the grid squares whose values are 24 | above or below a specified threshold. 25 | } 26 | \examples{ 27 | grid <- grid_metrics(SPIAT::defined_image, FUN = calculate_entropy, n_split = 5, 28 | cell_types_of_interest=c("Tumour","Immune3"), feature_colname = "Cell.Type") 29 | calculate_percentage_of_grids(grid, threshold = 0.75, above = TRUE) 30 | } 31 | -------------------------------------------------------------------------------- /man/calculate_proportions_of_cells_in_structure.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/calculate_proportions_of_cells_in_structure.R 3 | \name{calculate_proportions_of_cells_in_structure} 4 | \alias{calculate_proportions_of_cells_in_structure} 5 | \title{calculate_proportions_of_cells_in_structure} 6 | \usage{ 7 | calculate_proportions_of_cells_in_structure( 8 | spe_object, 9 | cell_types_of_interest, 10 | feature_colname 11 | ) 12 | } 13 | \arguments{ 14 | \item{spe_object}{SpatialExperiment object in the form of the output of 15 | \code{\link{format_image_to_spe}}.} 16 | 17 | \item{cell_types_of_interest}{String Vector of cell types to consider.} 18 | 19 | \item{feature_colname}{String. The name of the column where the cell 20 | types of interest are under.} 21 | } 22 | \value{ 23 | A data.frame 24 | } 25 | \description{ 26 | Calculate the proportion of cells of interest in each defined 27 | tissue structure relative to all cells in each structure and relative to 28 | the same cell type in the whole image. 29 | } 30 | \examples{ 31 | spe_border <- identify_bordering_cells(SPIAT::defined_image, 32 | reference_cell = "Tumour", feature_colname = "Cell.Type", n_to_exclude = 10) 33 | spe_dist <- calculate_distance_to_margin(spe_border) 34 | spe_structure <- define_structure(spe_dist, 35 | cell_types_of_interest = c("Immune1","Immune2","Immune3"), 36 | feature_colname = "Cell.Type", n_margin_layers = 5) 37 | calculate_proportions_of_cells_in_structure(spe_structure, 38 | cell_types_of_interest = c("Immune1","Immune3"),feature_colname="Cell.Type") 39 | } 40 | -------------------------------------------------------------------------------- /man/calculate_spatial_autocorrelation.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/calculate_spatial_autocorrelation.R 3 | \name{calculate_spatial_autocorrelation} 4 | \alias{calculate_spatial_autocorrelation} 5 | \title{calculate_spatial_autocorrelation} 6 | \usage{ 7 | calculate_spatial_autocorrelation(raster_obj, metric = "globalmoran", d = NULL) 8 | } 9 | \arguments{ 10 | \item{raster_obj}{Raster object in the form of the output of 11 | \code{\link{grid_metrics}}.} 12 | 13 | \item{metric}{String. The method for calculating spatial autocorrelation. 14 | Choose from "globalmoran" and "GearyC".} 15 | 16 | \item{d}{Numeric. Upper bound local distance. The argument `d2` from function 17 | \link[elsa]{moran}. Default is NULL and the distance will be calculated 18 | automatically from the number of splits and the extent of the grid image.} 19 | } 20 | \value{ 21 | A number is returned 22 | } 23 | \description{ 24 | Takes the result of \code{\link{grid_metrics}} (a RasterLayer 25 | object) and calculate its spatial autocorrelation. 26 | } 27 | \examples{ 28 | grid <- grid_metrics(SPIAT::defined_image, FUN = calculate_entropy, 29 | n_split = 5, cell_types_of_interest=c("Tumour","Immune3"), 30 | feature_colname = "Cell.Type") 31 | calculate_spatial_autocorrelation(grid, metric = "globalmoran") 32 | } 33 | -------------------------------------------------------------------------------- /man/calculate_summary_distances_between_celltypes.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/calculate_summary_distances_between_celltypes.R 3 | \name{calculate_summary_distances_between_celltypes} 4 | \alias{calculate_summary_distances_between_celltypes} 5 | \title{calculate_summary_distances_between_celltypes} 6 | \usage{ 7 | calculate_summary_distances_between_celltypes(df) 8 | } 9 | \arguments{ 10 | \item{df}{Data.frame containing the distance output between cell types. The 11 | functions that generate the distances can be 12 | \code{\link{calculate_minimum_distances_between_celltypes}} and 13 | \code{\link{calculate_pairwise_distances_between_celltypes}}.} 14 | } 15 | \value{ 16 | A data frame is returned 17 | } 18 | \description{ 19 | Returns the mean, median and standard deviation of the 20 | minimum/pairwise distances between phenotypes. 21 | } 22 | \examples{ 23 | # for pairwise dist 24 | pairwise_dist <- calculate_pairwise_distances_between_celltypes( 25 | SPIAT::defined_image, cell_types_of_interest = c("Tumour","Immune1"), 26 | feature_colname = "Cell.Type") 27 | summary_distances <- calculate_summary_distances_between_celltypes(pairwise_dist) 28 | 29 | # for minimum dist 30 | min_dists <- calculate_minimum_distances_between_celltypes( 31 | SPIAT::defined_image, cell_types_of_interest = c("Tumour","Immune1"), 32 | feature_colname = "Cell.Type") 33 | summary_distances <- calculate_summary_distances_between_celltypes(min_dists) 34 | } 35 | -------------------------------------------------------------------------------- /man/calculate_summary_distances_of_cells_to_borders.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in 3 | % R/calculate_summary_distances_of_cells_to_borders.R 4 | \name{calculate_summary_distances_of_cells_to_borders} 5 | \alias{calculate_summary_distances_of_cells_to_borders} 6 | \title{calculate_summary_distances_of_cells_to_borders} 7 | \usage{ 8 | calculate_summary_distances_of_cells_to_borders( 9 | spe_object, 10 | cell_types_of_interest, 11 | feature_colname = "Cell.Type" 12 | ) 13 | } 14 | \arguments{ 15 | \item{spe_object}{SpatialExperiment object. It should contain information of 16 | tissue structure and cell distances to the tissue region border (`colData()` has 17 | `Region` and `Distance.To.Border` columns).} 18 | 19 | \item{cell_types_of_interest}{String Vector of cell types to consider.} 20 | 21 | \item{feature_colname}{String specifying which column the interested cell 22 | types are from.} 23 | } 24 | \value{ 25 | A data.frame is returned 26 | } 27 | \description{ 28 | Returns the mean, median and standard deviation of the distances 29 | between a specified cell type to the border. 30 | } 31 | \examples{ 32 | spe_border <- identify_bordering_cells(SPIAT::defined_image, 33 | reference_cell = "Tumour", feature_colname = "Cell.Type", n_to_exclude = 10) 34 | spe_dist <- calculate_distance_to_margin(spe_border) 35 | spe_structure <- define_structure(spe_dist, cell_types_of_interest = 36 | c("Immune1","Immune2","Immune3"), feature_colname = "Cell.Type", 37 | n_margin_layers = 5) 38 | calculate_summary_distances_of_cells_to_borders(spe_structure, 39 | cell_types_of_interest = c("Immune1","Immune3"),feature_colname = "Cell.Type") 40 | } 41 | -------------------------------------------------------------------------------- /man/composition_of_neighborhoods.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/composition_of_neighborhoods.R 3 | \name{composition_of_neighborhoods} 4 | \alias{composition_of_neighborhoods} 5 | \title{composition_of_neighborhoods} 6 | \usage{ 7 | composition_of_neighborhoods(spe_object, feature_colname) 8 | } 9 | \arguments{ 10 | \item{spe_object}{SpatialExperiment that is the output of 11 | \code{\link{identify_neighborhoods}}.} 12 | 13 | \item{feature_colname}{String. Column with cell types.} 14 | } 15 | \value{ 16 | A data.frame is returned 17 | } 18 | \description{ 19 | Returns a data.frame which contains the percentages of cells 20 | with a specific marker within each neighborhood. and the number of cells in 21 | the neighborhood. 22 | } 23 | \examples{ 24 | neighborhoods <- identify_neighborhoods(image_no_markers, 25 | method = "hierarchical", min_neighborhood_size = 100, 26 | cell_types_of_interest = c("Immune", "Immune1", "Immune2"), radius = 50, 27 | feature_colname = "Cell.Type") 28 | neighborhoods_vis <- composition_of_neighborhoods(neighborhoods, 29 | feature_colname="Cell.Type") 30 | } 31 | -------------------------------------------------------------------------------- /man/compute_gradient.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/compute_gradient.R 3 | \name{compute_gradient} 4 | \alias{compute_gradient} 5 | \title{compute_gradient} 6 | \usage{ 7 | compute_gradient(spe_object, radii, FUN, ...) 8 | } 9 | \arguments{ 10 | \item{spe_object}{SpatialExperiment object in the form of the output of 11 | \code{\link{format_image_to_spe}}.} 12 | 13 | \item{radii}{Numeric Vector specifying the range of radii for the metrics to 14 | be calculated.} 15 | 16 | \item{FUN}{Variable name specifying the metric.} 17 | 18 | \item{...}{Arguments of FUN} 19 | } 20 | \value{ 21 | A list of the metrics under all radii 22 | } 23 | \description{ 24 | The function sweeps over circles of a range of radii surrounding 25 | reference cells and calculates the metrics at the radii. Metrics used with 26 | function need two conditions: 1) have a `radius` parameter. 2) return a 27 | single number. For metrics that do not return a single number, users can 28 | wrap them in a new function that returns a number and then pass the new 29 | function to `compute_gradient()`. 30 | } 31 | \examples{ 32 | gradient_positions <- c(30, 50, 100) 33 | gradient_entropy <- compute_gradient(SPIAT::defined_image, 34 | radii = gradient_positions, FUN = calculate_entropy, 35 | cell_types_of_interest = c("Immune1","Immune2"), 36 | feature_colname = "Cell.Type") 37 | } 38 | -------------------------------------------------------------------------------- /man/crossing_of_crossK.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/crossing_of_crossK.R 3 | \name{crossing_of_crossK} 4 | \alias{crossing_of_crossK} 5 | \title{crossing_of_crossK} 6 | \usage{ 7 | crossing_of_crossK(df.cross) 8 | } 9 | \arguments{ 10 | \item{df.cross}{Data.frame. The output of 11 | \code{\link{calculate_cross_functions}}. Containing the positions of the 12 | two curves. Columns contain "r", "border" and "theo".} 13 | } 14 | \value{ 15 | A number. The percentage of the crossing position of the specified 16 | distance. Returns NA when the crossing happens too close to the y axis (<4%). 17 | } 18 | \description{ 19 | Determine if there is a crossing in the cross K curves, to 20 | further detect the existence of potential immune rings. 21 | } 22 | \examples{ 23 | df_cross <- calculate_cross_functions(SPIAT::defined_image, method="Kcross", 24 | cell_types_of_interest = c("Tumour","Immune3"), 25 | feature_colname ="Cell.Type", dist = 100) 26 | crossing_of_crossK(df_cross) 27 | } 28 | -------------------------------------------------------------------------------- /man/define_celltypes.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/define_celltypes.R 3 | \name{define_celltypes} 4 | \alias{define_celltypes} 5 | \title{define_celltypes} 6 | \usage{ 7 | define_celltypes( 8 | spe_object, 9 | categories = NULL, 10 | category_colname = "Phenotype", 11 | names = NULL, 12 | new_colname = "Cell.Type", 13 | print_names = FALSE 14 | ) 15 | } 16 | \arguments{ 17 | \item{spe_object}{SpatialExperiment object in the form of the output of 18 | \code{\link{format_image_to_spe}}.} 19 | 20 | \item{categories}{Vector. Names of the old cell types to be defined; if NULL, 21 | the function will use predefined categories and names} 22 | 23 | \item{category_colname}{(Phenotype) String specifying the name of the column 24 | having the categories to be defined, by default "Phenotype".} 25 | 26 | \item{names}{Vector of new names assigned to the selected categories; if 27 | NULL, the function will use predefined categories and names. Should be of 28 | the same length of `categories`.} 29 | 30 | \item{new_colname}{(Optional) String specifying the name of the column to be 31 | added, by default "Cell.Type".} 32 | 33 | \item{print_names}{(Optional) Boolean if the user wants the original and new 34 | names printed. Default is FALSE.} 35 | } 36 | \value{ 37 | An new SPE object is returned 38 | } 39 | \description{ 40 | Define new cell types based on the existing cell types 41 | (categories) under a selected column (e.g. base on marker combinations 42 | under "Phenotype" column). This function will create a new column to store 43 | the new cell types. 44 | } 45 | \details{ 46 | Users need to specify the names of the old cell categories and under 47 | which column the old cell categories exist. Then the users specify the 48 | names of the new cell types and the name of the new column to store the new 49 | cell types. Any cell categories that are not specified in `categories` arg 50 | but present in the image will be defined as "Undefined" in the new column. 51 | } 52 | \examples{ 53 | # the selected column is: 54 | category_colname = "Phenotype" 55 | # define the following marker combinations: 56 | categories <- c("Tumour_marker", "Immune_marker1,Immune_marker2", 57 | "Immune_marker1,Immune_marker3", 58 | "Immune_marker1,Immune_marker2,Immune_marker4", "OTHER") 59 | # the new defined cell names: 60 | names = c("Tumour", "Immune1", "Immune2","Immune3", "Others") 61 | # the new names are stored under this column: 62 | new_colname <- "Cell.Type" 63 | 64 | defined_spe <- define_celltypes(SPIAT::simulated_image, 65 | categories = categories, category_colname = category_colname, names = names, 66 | new_colname = new_colname) 67 | } 68 | -------------------------------------------------------------------------------- /man/define_structure.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/define_structure.R 3 | \name{define_structure} 4 | \alias{define_structure} 5 | \title{define_structure} 6 | \usage{ 7 | define_structure( 8 | spe_object, 9 | cell_types_of_interest, 10 | feature_colname = "Cell.Type", 11 | n_margin_layers = 5, 12 | margin_dist = NULL 13 | ) 14 | } 15 | \arguments{ 16 | \item{spe_object}{SpatialExperiment object that contains information of 17 | tumour bordering cells and cell distances to border (`colData()` has 18 | `Region` and `Distance.To.Border` columns).} 19 | 20 | \item{cell_types_of_interest}{String Vector of the names of the particular 21 | types of cells.} 22 | 23 | \item{feature_colname}{String Specifying the column that contains the names 24 | of the immune cells.} 25 | 26 | \item{n_margin_layers}{Integer. The number of layers of cells that compose 27 | the internal/external margins. Default is 5.} 28 | 29 | \item{margin_dist}{Numeric. The width of the internal/external margins. 30 | Default is NULL. Only use when `n_margin_layers` is NULL.} 31 | } 32 | \value{ 33 | A new spe object is returned. Under the `Region` column, there will 34 | be potential categories including `Border` - the bordering cells, 35 | `Infiltrated.CoI` - cells of interest that present inside of the tissue 36 | regions, `Inside` - cells within the regiona excluding the 37 | `Infiltrated.CoI` cells and the cells at internal margin, `Stromal.CoI` - 38 | cells of interest that present outside of the tissue regions, `Outside` - 39 | cells outside of the tissue regions excluding the `Stromal.CoI` cells, 40 | `Internal.margin.CoI` - cells of interest that are in the internal margin 41 | of the tissue regions, `Internal.margin` - cells in the internal margin of 42 | the tissue regions excluding the `Internal.margin.CoI` cells, 43 | `External.margin.CoI` - cells of interest that are in the external margin 44 | of the tissue regions, `External.margin` - cells in the external margin of 45 | the tissue regions excluding the `External.margin.CoI` cells. 46 | } 47 | \description{ 48 | After identifying the bordering cells of tissue regions and 49 | calculating the distances of each cell to the bordering cells, this 50 | function further identifies the cells that are located in the inside and 51 | outside of the identified regions, and in the internal and external 52 | margins. It also identifies particular types of cells that are infiltrated, 53 | stromal, internal margin or external margin cells. 54 | } 55 | \examples{ 56 | spe_border <- identify_bordering_cells(SPIAT::defined_image, 57 | reference_cell = "Tumour", feature_colname = "Cell.Type", n_to_exclude = 10) 58 | spe_dist <- calculate_distance_to_margin(spe_border) 59 | spe_structure <- define_structure(spe_dist, 60 | cell_types_of_interest = c("Immune1","Immune2","Immune3"), 61 | feature_colname = "Cell.Type", n_margin_layers = 5) 62 | plot_cell_categories(spe_structure, feature_colname = "Structure") 63 | } 64 | -------------------------------------------------------------------------------- /man/defined_image.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/defined_image.R 3 | \docType{data} 4 | \name{defined_image} 5 | \alias{defined_image} 6 | \title{SPE object of a simulated image with defined cell types based on marker 7 | combinations.} 8 | \format{ 9 | An spe object. Assay contains 5 rows (markers) and 4951 columns 10 | (cells); colData contains 4951 rows (cells) and 3 columns (features). 11 | } 12 | \usage{ 13 | defined_image 14 | } 15 | \description{ 16 | A dataset that contains a formatted spe object with cell ids, phenotypes, 17 | defined cell types in `colData()` and marker intensities in `assays()`. (The 18 | cell locations are the same with the cells in \code{\link{simulated_image}}). 19 | } 20 | \seealso{ 21 | \code{\link{simulated_image}} \code{\link{image_no_markers}} 22 | } 23 | \keyword{datasets} 24 | -------------------------------------------------------------------------------- /man/dimensionality_reduction_plot.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/dimensionality_reduction_plot.R 3 | \name{dimensionality_reduction_plot} 4 | \alias{dimensionality_reduction_plot} 5 | \title{Dimensionality reduction plot} 6 | \usage{ 7 | dimensionality_reduction_plot( 8 | spe_object, 9 | plot_type = "UMAP", 10 | scale = TRUE, 11 | perplexity = 30, 12 | feature_colname 13 | ) 14 | } 15 | \arguments{ 16 | \item{spe_object}{SpatialExperiment object in the form of the output of 17 | \code{\link{format_image_to_spe}}.} 18 | 19 | \item{plot_type}{String. Choose from "UMAP" and "TSNE".} 20 | 21 | \item{scale}{Boolean. Whether scale the marker intensities.} 22 | 23 | \item{perplexity}{Numeric. Perplexity parameter of the Rtsne function (should 24 | be positive and no bigger than 3 * perplexity < n - 1, where n is the 25 | number of cells).} 26 | 27 | \item{feature_colname}{String. Specify the column name to group the cells.} 28 | } 29 | \value{ 30 | A plot 31 | } 32 | \description{ 33 | Generates the dimensionality reduction plots (UMAP or tSNE) 34 | based on marker intensities. Cells are grouped by the categories under the 35 | selected column. 36 | } 37 | \examples{ 38 | dimensionality_reduction_plot(SPIAT::simulated_image, plot_type = "TSNE", 39 | feature_colname = "Phenotype") 40 | } 41 | -------------------------------------------------------------------------------- /man/entropy_gradient_aggregated.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/entropy_gradient_aggregated.R 3 | \name{entropy_gradient_aggregated} 4 | \alias{entropy_gradient_aggregated} 5 | \title{The aggregated gradient of entropy and the peak of the gradient} 6 | \usage{ 7 | entropy_gradient_aggregated( 8 | spe_object, 9 | cell_types_of_interest, 10 | feature_colname, 11 | radii 12 | ) 13 | } 14 | \arguments{ 15 | \item{spe_object}{SpatialExperiment object in the form of the output of 16 | \code{\link{format_image_to_spe}}.} 17 | 18 | \item{cell_types_of_interest}{String Vector. The cell types that the entropy 19 | is computed on.} 20 | 21 | \item{feature_colname}{String. The column name of the interested cell types.} 22 | 23 | \item{radii}{Numeric Vector. A vector of radii within a circle of a reference 24 | cell where the entropy is computed on.} 25 | } 26 | \value{ 27 | A list of the gradient of entropy and the peak 28 | } 29 | \description{ 30 | This function first calculates the entropy within circles of 31 | each reference cell at each radius. Then at each radius, the entropy of all 32 | circles surrounding each cell are aggregated into one number. The function 33 | sweeps over the specified radii and calculates the aggregated entropy under 34 | each radius. 35 | } 36 | \examples{ 37 | gradient_pos <- seq(50, 500, 50) 38 | gradient_results <- entropy_gradient_aggregated(SPIAT::defined_image, 39 | cell_types_of_interest = c("Tumour","Immune3"), 40 | feature_colname = "Cell.Type", radii = gradient_pos) 41 | plot(1:10,gradient_results$gradient_df[1, 3:12]) 42 | } 43 | -------------------------------------------------------------------------------- /man/format_cellprofiler_to_spe.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/format_cellprofiler_to_spe.R 3 | \name{format_cellprofiler_to_spe} 4 | \alias{format_cellprofiler_to_spe} 5 | \title{Format a cellprofiler image into a SpatialExperiment object} 6 | \usage{ 7 | format_cellprofiler_to_spe( 8 | path = NULL, 9 | markers = NULL, 10 | intensity_columns_interest = NULL 11 | ) 12 | } 13 | \arguments{ 14 | \item{path}{String of the path location cellprofiler csv file.} 15 | 16 | \item{markers}{String Vector containing the markers used for staining.} 17 | 18 | \item{intensity_columns_interest}{String Vector with the names of the columns 19 | with the level of each marker. Column names must match the order of the 20 | 'markers' parameter.} 21 | } 22 | \value{ 23 | A SpatialExperiment object is returned 24 | } 25 | \description{ 26 | Reads in spatial data in the form of cell coordinates, cell 27 | phenotypes (if available), and marker intensities and transforms to a 28 | SpatialExperiment object. The assay stores the intensity level of every 29 | marker (rows) for every cell (columns). Cell phenotype is stored under 30 | `colData()`. Cell x and y coordinates are stored under `spatialCoords()` 31 | Note that if the data does not include these parameters, we recommend 32 | adding it to the output from cellprofiler with NAs in columns. 33 | } 34 | \details{ 35 | Note when specifying `markers`, please use "DAPI" to replace "DNA" 36 | due to implementation. The output data will include "DAPI" instead of 37 | "DNA". 38 | } 39 | \examples{ 40 | path <- system.file("extdata", "tiny_cellprofiler.txt.gz", package = "SPIAT") 41 | markers <- c("Marker1", "Marker2", "Marker3", "Marker4", "Marker5", "DAPI", 42 | "Marker6") 43 | intensity_columns_interest <- c("Intensity_MeanIntensity_Marker1_rs", 44 | "Intensity_MeanIntensity_Marker2_rs", "Intensity_MeanIntensity_Marker3_rs", 45 | "Intensity_MeanIntensity_Marker4_rs", "Intensity_MeanIntensity_Marker5_rs", 46 | "Intensity_MeanIntensity_DAPI_rs", "Intensity_MeanIntensity_Marker6_rs") 47 | formatted_cellprofiler <- format_cellprofiler_to_spe(path = path, 48 | markers = markers, intensity_columns_interest = intensity_columns_interest) 49 | } 50 | -------------------------------------------------------------------------------- /man/format_codex_to_spe.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/format_codex_to_spe.R 3 | \name{format_codex_to_spe} 4 | \alias{format_codex_to_spe} 5 | \title{Format a CODEX image into a SpatialExperiment object} 6 | \usage{ 7 | format_codex_to_spe(path = NULL, markers, path_to_codex_cell_phenotypes = NULL) 8 | } 9 | \arguments{ 10 | \item{path}{String of the path location of CODEX csv file.} 11 | 12 | \item{markers}{String Vector containing the markers used for staining.} 13 | 14 | \item{path_to_codex_cell_phenotypes}{String of the path to 15 | the Cluster ID/Cell type file.} 16 | } 17 | \value{ 18 | A SpatialExperiment object is returned 19 | } 20 | \description{ 21 | Reads in spatial data in the form of cell coordinates, cell 22 | phenotypes (if available), and marker intensities and transforms to a 23 | `SpatialExperiment` object. The assay stores the intensity level of every marker 24 | (rows) for every cell (columns). Cell phenotype is stored under colData. 25 | Cell x and y coordinates are stored under `spatialCoords()` field. 26 | } 27 | \examples{ 28 | path <- system.file("extdata", "tiny_codex.csv.gz", package = "SPIAT") 29 | path_to_codex_cell_phenotypes <- system.file("extdata", 30 | "tiny_codex_phenotypes.txt.gz", package = "SPIAT") 31 | markers <- c("CD45", "Ly6C", "CD27", "CD5", "CD79b") 32 | formatted_codex <- format_codex_to_spe(path = path, markers = markers, 33 | path_to_codex_cell_phenotypes = path_to_codex_cell_phenotypes) 34 | } 35 | -------------------------------------------------------------------------------- /man/format_colData_to_spe.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/format_colData_to_spe.R 3 | \name{format_colData_to_spe} 4 | \alias{format_colData_to_spe} 5 | \title{format_colData_to_spe} 6 | \usage{ 7 | format_colData_to_spe(df) 8 | } 9 | \arguments{ 10 | \item{df}{Data frame that contains cell coordinates, phenotypes (if 11 | available) and other cell properties. The rownames should be cell ID} 12 | } 13 | \value{ 14 | An SpatialExperiment object 15 | } 16 | \description{ 17 | Format a data frame into a SpatialExperiment class where the 18 | count assay is empty every cell (columns), cell phenotypes are stored under 19 | colData() and cell coordinates are stored under spatialCoords(). 20 | } 21 | \examples{ 22 | df <- data.frame(row.names = c("Cell_1", "Cell_2"), Cell.X.Position = c(2,5), 23 | Cell.Y.Position = c(3.3, 8), Phenotypes = c("CD3", "CD3,CD8")) 24 | spe <- format_colData_to_spe(df) 25 | } 26 | -------------------------------------------------------------------------------- /man/format_halo_to_spe.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/format_HALO_to_spe.R 3 | \name{format_halo_to_spe} 4 | \alias{format_halo_to_spe} 5 | \title{Format a HALO image into a SpatialExperiment object} 6 | \usage{ 7 | format_halo_to_spe( 8 | path = NULL, 9 | markers = NULL, 10 | locations = NULL, 11 | dye_columns_interest = NULL, 12 | intensity_columns_interest = NULL 13 | ) 14 | } 15 | \arguments{ 16 | \item{path}{String of the path location of HALO text file.} 17 | 18 | \item{markers}{String Vector containing the markers used for staining.} 19 | 20 | \item{locations}{(Optional) Vector containing the locations of markers used for 21 | staining. Location can be either "Nucleus", "Cytoplasm" or "Membrane". This 22 | is used to select the Intensity column and can be used instead of 23 | `intensity_columns_interest`.} 24 | 25 | \item{dye_columns_interest}{(Optional) Use if locations is not 26 | specified. Vector of names of the columns with the marker status (i.e. 27 | those indicating 1 or 0 for whether the cell is positive or negative for 28 | the marker). Column names must match the order of the 'markers' parameter.} 29 | 30 | \item{intensity_columns_interest}{(Optional) Use if locations is not 31 | specified. Vector with the names of the columns with the level of each 32 | marker. Column names must match the order of the 'markers' parameter.} 33 | } 34 | \value{ 35 | A SpatialExperiment object is returned 36 | } 37 | \description{ 38 | Reads in HALO data in the form of cell coordinates, cell 39 | phenotypes (if available), and marker intensities and transforms to a 40 | `SpatialExperiment` object. The assay stores the intensity level of every 41 | marker (rows) for every cell (columns). Cell x and y coordinates are stored 42 | under `spatialCoords()`. Cell phenotype and other cell properties are 43 | stored under colData. The cell properties to be included are Cell.Area, 44 | Nucleus.Area and Cytoplasm.Area. Note that if the data does not include 45 | these parameters, we recommend adding it to the output from HALO with NAs 46 | in columns. 47 | } 48 | \examples{ 49 | raw_halo_data <- system.file("extdata", "tiny_halo.csv.gz", package="SPIAT") 50 | markers <- c("DAPI", "CD3", "PDL-1", "CD4", "CD8", "AMACR") 51 | intensity_columns_interest <- c("Dye 1 Nucleus Intensity", 52 | "Dye 2 Cytoplasm Intensity","Dye 3 Membrane Intensity", 53 | "Dye 4 Cytoplasm Intensity", "Dye 5 Cytoplasm Intensity", 54 | "Dye 6 Cytoplasm Intensity") 55 | dye_columns_interest <-c("Dye 1 Positive Nucleus","Dye 2 Positive Cytoplasm", 56 | "Dye 3 Positive Membrane", "Dye 4 Positive Cytoplasm", 57 | "Dye 5 Positive Cytoplasm", "Dye 6 Positive Cytoplasm") 58 | formatted_HALO <- format_halo_to_spe(path=raw_halo_data,markers=markers, 59 | intensity_columns_interest=intensity_columns_interest, 60 | dye_columns_interest=dye_columns_interest) 61 | } 62 | -------------------------------------------------------------------------------- /man/format_inform_to_spe.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/format_inform_to_spe.R 3 | \name{format_inform_to_spe} 4 | \alias{format_inform_to_spe} 5 | \title{Format an inForm image into a SpatialExperiment object} 6 | \usage{ 7 | format_inform_to_spe( 8 | path, 9 | markers, 10 | locations = NULL, 11 | intensity_columns_interest = NULL 12 | ) 13 | } 14 | \arguments{ 15 | \item{path}{String of the path location of inForm text file.} 16 | 17 | \item{markers}{String Vector containing the markers used for staining.} 18 | 19 | \item{locations}{(Optional) String Vector containing the locations of markers 20 | used for staining. Location can be either "Nucleus", "Cytoplasm" or 21 | "Membrane". This is used to select the Intensity column and can be used 22 | instead of `intensity_columns_interest`.} 23 | 24 | \item{intensity_columns_interest}{(Optional) Use if `locations` is not 25 | specified. Vector with the names of the columns with the level of each 26 | marker. Column names must match the order of the 'markers' parameter.} 27 | } 28 | \value{ 29 | A SpatialExperiment object is returned 30 | } 31 | \description{ 32 | Reads in inForm data in the form of cell coordinates, cell 33 | phenotypes (if available), and marker intensities and transforms to a 34 | SpatialExperiment object. The assay stores the intensity level of 35 | every marker (rows) for every cell (columns). Cell phenotype, x and y 36 | coordinates and other cell properties are stored under colData. The cell 37 | properties to include are Cell.Area, Nucleus.Area, Nucleus.Compactness, 38 | Nucleus.Axis.Ratio, and Cell.Axis.Ratio. Note that if the data does not 39 | include these parameters, we recommend adding it to the output from inForm 40 | with NAs in columns. 41 | } 42 | \examples{ 43 | raw_inform_data<-system.file("extdata","tiny_inform.txt.gz",package="SPIAT") 44 | markers <- c("DAPI", "CD3", "PD-L1", "CD4", "CD8", "AMACR") 45 | locations <- c("Nucleus", "Cytoplasm", "Membrane", "Cytoplasm", "Cytoplasm", 46 | "Cytoplasm") 47 | formatted_inForm <- format_inform_to_spe(path=raw_inform_data, 48 | markers=markers, locations=locations) 49 | } 50 | -------------------------------------------------------------------------------- /man/format_spe_to_ppp.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/format_spe_to_ppp.R 3 | \name{format_spe_to_ppp} 4 | \alias{format_spe_to_ppp} 5 | \title{Format SPE object as a ppp object (`spatstat` package)} 6 | \usage{ 7 | format_spe_to_ppp( 8 | spe_object, 9 | window_pol = FALSE, 10 | feature_colname = "Phenotype" 11 | ) 12 | } 13 | \arguments{ 14 | \item{spe_object}{SpatialExperiment object in the form of the output of 15 | format_image_to_spe.} 16 | 17 | \item{window_pol}{Optional Boolean Specifying if the window is polygon.} 18 | 19 | \item{feature_colname}{String specifying the feature column of interest.} 20 | } 21 | \value{ 22 | A ppp object is returned (defined in `spatstat` package) 23 | } 24 | \description{ 25 | Formats an spe object into a ppp object which has the x,y 26 | coordinates, phenotypes as markers window specifies the range of x and y 27 | coordinates 28 | } 29 | \examples{ 30 | ppp_object<-format_spe_to_ppp(SPIAT::defined_image, 31 | feature_colname = "Cell.Type") 32 | } 33 | -------------------------------------------------------------------------------- /man/grid_metrics.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/grid_metrics.R 3 | \name{grid_metrics} 4 | \alias{grid_metrics} 5 | \title{Split an image into grid and calculates a metric for each grid square} 6 | \usage{ 7 | grid_metrics(spe_object, FUN, n_split, ...) 8 | } 9 | \arguments{ 10 | \item{spe_object}{SpatialExperiment object in the form of the output of 11 | \code{\link{format_image_to_spe}}.} 12 | 13 | \item{FUN}{Variable name specifying the metric to be calculated.} 14 | 15 | \item{n_split}{Integer specifying the number of splits for the calculation of 16 | metrics. This number is the splits on each side (e.g. `n_split` = 3 means 17 | the image will be split into 9 tiles.)} 18 | 19 | \item{...}{Arguments of FUN} 20 | } 21 | \value{ 22 | A list of the metrics of all grid tiles 23 | } 24 | \description{ 25 | Calculates a specified metric for each grid tile in the image 26 | and plots the metrics for the grid tiles. 27 | } 28 | \examples{ 29 | grid <- grid_metrics(SPIAT::defined_image, FUN = calculate_entropy, n_split = 5, 30 | cell_types_of_interest=c("Tumour","Immune3"), feature_colname = "Cell.Type") 31 | } 32 | -------------------------------------------------------------------------------- /man/identify_bordering_cells.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/identify_bordering_cells.R 3 | \name{identify_bordering_cells} 4 | \alias{identify_bordering_cells} 5 | \title{identify_bordering_cells} 6 | \usage{ 7 | identify_bordering_cells( 8 | spe_object, 9 | reference_cell, 10 | feature_colname = "Cell.Type", 11 | ahull_alpha = NULL, 12 | n_to_exclude = 10, 13 | plot_final_border = TRUE 14 | ) 15 | } 16 | \arguments{ 17 | \item{spe_object}{SpatialExperiment object in the form of the output of 18 | \code{\link{format_image_to_spe}}.} 19 | 20 | \item{reference_cell}{String. Cells of this cell type will be used for border 21 | detection.} 22 | 23 | \item{feature_colname}{String that specifies the column of `reference_cell`.} 24 | 25 | \item{ahull_alpha}{Number specifying the parameter for the alpha hull 26 | algorithm. The larger the number, the more cells will be included in one 27 | cell cluster.} 28 | 29 | \item{n_to_exclude}{Integer. Clusters with cell count under this number will 30 | be deleted.} 31 | 32 | \item{plot_final_border}{Boolean if plot the identified bordering cells.} 33 | } 34 | \value{ 35 | A new SPE object is returned. The SPE object has a `Region` column 36 | with "Border", "Inside" and "Outside" categories. The returned object also 37 | has an attribute saving the number of clusters. 38 | } 39 | \description{ 40 | Identify the cells bordering a group of cells of a particular 41 | phenotype, and calculate the number of clustered groups of this cell type. 42 | } 43 | \details{ 44 | The bordering cell detection algorithm is based on computing an 45 | alpha hull (Hemmer et al., 2020), a generalization of convex hull (Green 46 | and Silverman, 1979). The cells detected to be on the alpha hull are 47 | identified as the bordering cells. 48 | } 49 | \examples{ 50 | spe_border <- identify_bordering_cells(SPIAT::defined_image, 51 | reference_cell = "Tumour", feature_colname = "Cell.Type", n_to_exclude = 10) 52 | n_clusters <- attr(spe_border, "n_of_clusters") # get the number of clusters 53 | n_clusters 54 | } 55 | -------------------------------------------------------------------------------- /man/identify_neighborhoods.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/identify_neighborhoods.R 3 | \name{identify_neighborhoods} 4 | \alias{identify_neighborhoods} 5 | \title{identify_neighborhoods} 6 | \usage{ 7 | identify_neighborhoods( 8 | spe_object, 9 | method = "hierarchical", 10 | cell_types_of_interest, 11 | radius, 12 | min_neighborhood_size = 10, 13 | k = 100, 14 | feature_colname, 15 | no_pheno = NULL 16 | ) 17 | } 18 | \arguments{ 19 | \item{spe_object}{SpatialExperiment object in the form of the output of 20 | \code{\link{format_image_to_spe}}.} 21 | 22 | \item{method}{String. The clustering method. Choose from "hierarchical", 23 | "dbscan" and "Rphenograph". (Note Rphenograph function is not available for 24 | this version yet).} 25 | 26 | \item{cell_types_of_interest}{String Vector of phenotypes to consider.} 27 | 28 | \item{radius}{Numeric specifying the radius of search. Need to specify when 29 | `method` is "hierarchical" or "dbscan".} 30 | 31 | \item{min_neighborhood_size}{Numeric. The minimum number of cells within each 32 | cluster. Need to specify when `method` is "hierarchical" or "dbscan".} 33 | 34 | \item{k}{Numeric. The parameter for "Rphenograph" method.} 35 | 36 | \item{feature_colname}{String. Column from which the cell types are selected.} 37 | 38 | \item{no_pheno}{Cell type corresponding to cells without a known phenotype 39 | (e.g. "None", "Other")} 40 | } 41 | \value{ 42 | An spe object and a plot is returned. The spe object contains 43 | information of the defined neighborhood under "Neighborhood" column. The 44 | cells of interest that do not form clusters are labelled "Free_cell", cells 45 | not of interest are labelled `NA`. 46 | } 47 | \description{ 48 | Uses Euclidean distances to identify neighborhoods of cells. 49 | Three clustering methods are available, including hierarchical clustering, 50 | dbscan, and (Rphenograph). 51 | } 52 | \examples{ 53 | neighborhoods <- identify_neighborhoods(image_no_markers, method = "hierarchical", 54 | min_neighborhood_size = 100, cell_types_of_interest = c("Immune", "Immune1", "Immune2"), 55 | radius = 50, feature_colname = "Cell.Type") 56 | } 57 | -------------------------------------------------------------------------------- /man/image_no_markers.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/image_no_markers.R 3 | \docType{data} 4 | \name{image_no_markers} 5 | \alias{image_no_markers} 6 | \title{SPE object of a formatted image without marker intensities (simulated by 7 | `spaSim` package)} 8 | \format{ 9 | An spe object. colData contains 4951 rows (cells) and 3 columns 10 | (features). 11 | } 12 | \usage{ 13 | image_no_markers 14 | } 15 | \description{ 16 | A dataset that contains a formatted spe object with cell ids and cell types 17 | in `colData()` and cell coordinates in `spatialCoords()`. This dataset does 18 | not contain assays (marker intensities). 19 | } 20 | \seealso{ 21 | \code{\link{defined_image}} \code{\link{simulated_image}} 22 | } 23 | \keyword{datasets} 24 | -------------------------------------------------------------------------------- /man/image_splitter.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/image_splitter.R 3 | \name{image_splitter} 4 | \alias{image_splitter} 5 | \title{Split a large image into sub images} 6 | \usage{ 7 | image_splitter( 8 | spe_object, 9 | number_of_splits, 10 | plot = FALSE, 11 | cut_labels = TRUE, 12 | colour_vector = NULL, 13 | minX = NULL, 14 | maxX = NULL, 15 | minY = NULL, 16 | maxY = NULL, 17 | feature_colname = "Phenotype" 18 | ) 19 | } 20 | \arguments{ 21 | \item{spe_object}{`SpatialExperiment` object in the form of the output of 22 | \code{\link{format_image_to_spe}}.} 23 | 24 | \item{number_of_splits}{Numeric. specifying the number of segments (e.g. 2 = 25 | 2x2, 3 = 3x3).} 26 | 27 | \item{plot}{Boolean. Specifies whether the splitted images should be printed 28 | in a pdf.} 29 | 30 | \item{cut_labels}{Boolean. Specifies whether to plot where the image had been 31 | segmented.} 32 | 33 | \item{colour_vector}{String Vector. If specified, the colours will be used 34 | for plotting. If NULL, colors will be generated automatically.} 35 | 36 | \item{minX}{Integer used to specify the minimum x boundary to be 37 | splitted.} 38 | 39 | \item{maxX}{Integer used to specify the maximum x boundary to be 40 | splitted.} 41 | 42 | \item{minY}{Integer used to specify the minimum y boundary to be 43 | splitted.} 44 | 45 | \item{maxY}{Integer used to specify the maximum y boundary to be 46 | splitted.} 47 | 48 | \item{feature_colname}{String specifying which column the colouring should be 49 | based on. Specify when `plot` is TRUE. Default is "Phenotype".} 50 | } 51 | \value{ 52 | A list of spe objects is returned. Each data frame represents an 53 | image without assay data. 54 | } 55 | \description{ 56 | Takes in an image in SpatialExperiment format, splits the image 57 | into specified sections and returns a list of SpatialExperiment objects. 58 | Users can choose to plot the cell positions in each sub image. Note that 59 | this function does not split the assay. 60 | } 61 | \examples{ 62 | split_image <- image_splitter(SPIAT::simulated_image, number_of_splits=3, 63 | plot = FALSE) 64 | } 65 | -------------------------------------------------------------------------------- /man/marker_intensity_boxplot.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/marker_intensity_boxplot.R 3 | \name{marker_intensity_boxplot} 4 | \alias{marker_intensity_boxplot} 5 | \title{marker_intensity_boxplot} 6 | \usage{ 7 | marker_intensity_boxplot(spe_object, marker, feature_colname = "Phenotype") 8 | } 9 | \arguments{ 10 | \item{spe_object}{SpatialExperiment object in the form of the output of 11 | \code{\link{format_image_to_spe}}.} 12 | 13 | \item{marker}{String. Marker being queried.} 14 | 15 | \item{feature_colname}{String. Column containing marker information} 16 | } 17 | \value{ 18 | A plot is returned 19 | } 20 | \description{ 21 | Produces boxplots of marker levels for cells phenotyped as being 22 | positive for the marker, and those that where phenotyped as being negative. 23 | } 24 | \examples{ 25 | marker_intensity_boxplot(SPIAT::simulated_image, "Immune_marker1") 26 | } 27 | -------------------------------------------------------------------------------- /man/marker_prediction_plot.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/marker_prediction_plot.R 3 | \name{marker_prediction_plot} 4 | \alias{marker_prediction_plot} 5 | \title{marker_prediction_plot} 6 | \usage{ 7 | marker_prediction_plot(predicted_data, marker) 8 | } 9 | \arguments{ 10 | \item{predicted_data}{Output from \code{\link{predict_phenotypes}}.} 11 | 12 | \item{marker}{String. Marker to plot} 13 | } 14 | \value{ 15 | A plot is returned 16 | } 17 | \description{ 18 | Takes in the returned dataframe from marker_threshold_plot and 19 | generates a .pdf file containing scatter plots of actual intensity and 20 | predicted intensity for every marker. 21 | } 22 | \examples{ 23 | predicted_result <- predict_phenotypes(spe_object = simulated_image, thresholds = NULL, 24 | tumour_marker = "Tumour_marker",baseline_markers = c("Immune_marker1", "Immune_marker2", 25 | "Immune_marker3", "Immune_marker4"), reference_phenotypes = TRUE) 26 | marker_prediction_plot(predicted_result, marker = "Tumour_marker") 27 | } 28 | -------------------------------------------------------------------------------- /man/marker_surface_plot.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/marker_surface_plot.R 3 | \name{marker_surface_plot} 4 | \alias{marker_surface_plot} 5 | \title{marker_surface_plot} 6 | \usage{ 7 | marker_surface_plot( 8 | spe_object, 9 | num_splits, 10 | marker, 11 | x_position_min = NULL, 12 | x_position_max = NULL, 13 | y_position_min = NULL, 14 | y_position_max = NULL 15 | ) 16 | } 17 | \arguments{ 18 | \item{spe_object}{SpatialExperiment object in the form of the output of 19 | \code{\link{format_image_to_spe}}.} 20 | 21 | \item{num_splits}{Integer specifying the number of splits on the image, 22 | higher splits equal to higher resolution. Recommendation: 10-100} 23 | 24 | \item{marker}{Marker to plot} 25 | 26 | \item{x_position_min}{Integer specifying the minimum x boundary to be 27 | splitted} 28 | 29 | \item{x_position_max}{Integer specifying the maximum x boundary to be 30 | splitted} 31 | 32 | \item{y_position_min}{Integer specifying the minimum y boundary to be 33 | splitted} 34 | 35 | \item{y_position_max}{Integer specifying the maximum y boundary to be 36 | splitted} 37 | } 38 | \value{ 39 | A plot is returned 40 | } 41 | \description{ 42 | Generates a 3D surface plot of the level of the selected marker. 43 | Note that the image is blurred based on the 'num_splits' parameter. 44 | } 45 | \examples{ 46 | marker_surface_plot(SPIAT::simulated_image, num_splits=15, marker="Immune_marker1") 47 | } 48 | -------------------------------------------------------------------------------- /man/marker_surface_plot_stack.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/marker_surface_plot_stack.R 3 | \name{marker_surface_plot_stack} 4 | \alias{marker_surface_plot_stack} 5 | \title{marker_surface_plot_stack} 6 | \usage{ 7 | marker_surface_plot_stack( 8 | spe_object, 9 | num_splits, 10 | markers_to_plot, 11 | sep = 1, 12 | x_position_min = NULL, 13 | x_position_max = NULL, 14 | y_position_min = NULL, 15 | y_position_max = NULL 16 | ) 17 | } 18 | \arguments{ 19 | \item{spe_object}{SpatialExperiment object in the form of the output of 20 | \code{\link{format_image_to_spe}}.} 21 | 22 | \item{num_splits}{Integer specifying the number of splits on the image, 23 | higher splits equal to higher resolution. Recommendation: 10-100.} 24 | 25 | \item{markers_to_plot}{Vector of marker names for plotting.} 26 | 27 | \item{sep}{Integer specifying the distance separation between each surface 28 | plot. We recommend values in the 1-2 range.} 29 | 30 | \item{x_position_min}{Integer specifying the minimum x boundary to be 31 | splitted.} 32 | 33 | \item{x_position_max}{Integer specifying the maximum x boundary to be 34 | splitted.} 35 | 36 | \item{y_position_min}{Integer specifying the minimum y boundary to be 37 | splitted.} 38 | 39 | \item{y_position_max}{Integer specifying the maximum y boundary to be 40 | splitted.} 41 | } 42 | \value{ 43 | A plot is returned 44 | } 45 | \description{ 46 | Generates stacked 3D surface plots showing normalized intensity 47 | level of specified markers. 48 | } 49 | \examples{ 50 | marker_surface_plot_stack(SPIAT::simulated_image, num_splits=15, 51 | markers=c("Tumour_marker", "Immune_marker4")) 52 | } 53 | -------------------------------------------------------------------------------- /man/measure_association_to_cell_properties.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/measure_association_to_cell_properties.R 3 | \name{measure_association_to_cell_properties} 4 | \alias{measure_association_to_cell_properties} 5 | \title{measure_association_to_cell_properties} 6 | \usage{ 7 | measure_association_to_cell_properties( 8 | spe_object, 9 | property = "Cell.Area", 10 | celltypes, 11 | feature_colname = "Cell.Type", 12 | method = "density", 13 | Nucleus.Ratio = FALSE, 14 | log.scale = FALSE 15 | ) 16 | } 17 | \arguments{ 18 | \item{spe_object}{SpatialExperiment object in the form of the output of 19 | \code{\link{format_image_to_spe}}.} 20 | 21 | \item{property}{String that is the name of the column of interest.} 22 | 23 | \item{celltypes}{String Vector of celltypes of interest.} 24 | 25 | \item{feature_colname}{String that speficies the column of the cell types.} 26 | 27 | \item{method}{String. The analysis to perform on the selected cell types and 28 | property. Options are "density", "box", "t", "wilcox".} 29 | 30 | \item{Nucleus.Ratio}{Boolean whether the ratio of the nucleus size is of 31 | interest.} 32 | 33 | \item{log.scale}{Boolean whether to log the data.} 34 | } 35 | \value{ 36 | With method "box" or "density a plot is returned. With method "t" or 37 | "wilcox", the text output from the test are returned. 38 | } 39 | \description{ 40 | Plots the density or boxplot of a property of two cell celltypes 41 | or compares using t test/wilcoxon rank sum test. 42 | } 43 | \examples{ 44 | measure_association_to_cell_properties(image_no_markers, 45 | celltypes = c("Tumour", "Immune1"), 46 | feature_colname = "Cell.Type", 47 | property = "Cell.Size", 48 | method = "box") 49 | measure_association_to_cell_properties(image_no_markers, 50 | celltypes = c("Tumour", "Immune2"), 51 | feature_colname="Cell.Type", 52 | property = "Cell.Size", 53 | method = "t") 54 | } 55 | -------------------------------------------------------------------------------- /man/mixing_score_summary.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/mixing_score_summary.R 3 | \name{mixing_score_summary} 4 | \alias{mixing_score_summary} 5 | \title{Calculate the (normalised) mixing score for interested cell types} 6 | \usage{ 7 | mixing_score_summary( 8 | spe_object, 9 | reference_celltype, 10 | target_celltype, 11 | radius = 20, 12 | feature_colname 13 | ) 14 | } 15 | \arguments{ 16 | \item{spe_object}{SpatialExperiment object in the form of the output of 17 | \code{\link{format_image_to_spe}}.} 18 | 19 | \item{reference_celltype}{String Vector. Cell types of the reference cells.} 20 | 21 | \item{target_celltype}{String Vector. Cell types of the target cells.} 22 | 23 | \item{radius}{The maximum radius around a reference cell type for another 24 | cell to be considered an interaction.} 25 | 26 | \item{feature_colname}{String specifying the column with the desired cell 27 | type annotations.} 28 | } 29 | \value{ 30 | A data.frame of cell numbers, number of cell interactions, mixing 31 | scores, and normalised mixing scores. If there are no reference or target 32 | cells found in the image, or there are no reference cells found within the 33 | specified radius of any reference cells,the returned (normalised) mixing 34 | scores will be NA. If there are no target cells found within the radius of 35 | any refernece cells, the returned (normalised) mixing scores will be 0. 36 | } 37 | \description{ 38 | Produces a data.frame with mixing scores of input reference and 39 | target cells from a SpatialExperiment object. It calculates 40 | reference-target interactions and reference-reference interactions based on 41 | a radius. It derives the mixing score and the normalised mixing score. 42 | Function returns NA if the mixing score is being calculated between cells 43 | of the same type. 44 | } 45 | \details{ 46 | The mixing score was originally defined as the number of 47 | immune-tumour interactions divided by the number of immune-immune 48 | interactions within a defined radius (Keren et al., 2018). The normalised 49 | mixing score normalises the immune-tumour interactions and immune-immune 50 | interactions within radius by the total number of immune-tumour and 51 | immune-immune interactions in the image, respectively. We have generalized 52 | this score to allow calculation of any two cell phenotypes defined by the 53 | user. 54 | } 55 | \examples{ 56 | mixing_score_summary(SPIAT::defined_image, reference_celltype = "Tumour", target_celltype="Immune1", 57 | radius = 50, feature_colname = "Cell.Type") 58 | } 59 | -------------------------------------------------------------------------------- /man/number_of_cells_within_radius.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/number_of_cells_within_radius.R 3 | \name{number_of_cells_within_radius} 4 | \alias{number_of_cells_within_radius} 5 | \title{Number of cells within a radius} 6 | \usage{ 7 | number_of_cells_within_radius( 8 | spe_object, 9 | reference_celltype, 10 | target_celltype, 11 | radius = 20, 12 | feature_colname 13 | ) 14 | } 15 | \arguments{ 16 | \item{spe_object}{SpatialExperiment object in the form of the output of 17 | \code{\link{format_image_to_spe}}.} 18 | 19 | \item{reference_celltype}{String. Cell type to be used for reference cells.} 20 | 21 | \item{target_celltype}{String. Cell type to be used for target cells.} 22 | 23 | \item{radius}{Numeric. Radius around the reference cells.} 24 | 25 | \item{feature_colname}{String specifying the column with the desired cell 26 | type annotations.} 27 | } 28 | \value{ 29 | A list of dataframes with the number of target cells of each of the 30 | reference cells 31 | } 32 | \description{ 33 | Calculates the number of cells of a target cell type 34 | within a pre-defined radius around cells of a reference cell type. 35 | } 36 | \examples{ 37 | n_in_radius <- number_of_cells_within_radius(SPIAT::defined_image, 38 | reference_celltype = "Tumour", target_celltype="Immune1", radius = 50, 39 | feature_colname = "Cell.Type") 40 | } 41 | -------------------------------------------------------------------------------- /man/plot_average_intensity.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/plot_average_intensity.R 3 | \name{plot_average_intensity} 4 | \alias{plot_average_intensity} 5 | \title{plot_average_intensity} 6 | \usage{ 7 | plot_average_intensity(spe_object, reference_marker, target_marker, radii) 8 | } 9 | \arguments{ 10 | \item{spe_object}{SpatialExperiment object in the form of the output of 11 | \code{\link{format_image_to_spe}}.} 12 | 13 | \item{reference_marker}{String specifying the reference marker.} 14 | 15 | \item{target_marker}{String specifying the marker to calculate its average 16 | intensity.} 17 | 18 | \item{radii}{Numeric Vector specifying the search radius around reference 19 | cells.} 20 | } 21 | \value{ 22 | A plot is returned 23 | } 24 | \description{ 25 | Takes in a vector or radii and calculates the average intensity 26 | of a target marker using average_intensity function. It plots the intensity 27 | level as a line graph. 28 | } 29 | \examples{ 30 | plot_average_intensity(SPIAT::simulated_image, reference_marker="Immune_marker3", 31 | target_marker="Immune_marker2", c(30, 35, 40, 45, 50, 75, 100)) 32 | } 33 | -------------------------------------------------------------------------------- /man/plot_cell_categories.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/plot_cell_categories.R 3 | \name{plot_cell_categories} 4 | \alias{plot_cell_categories} 5 | \title{plot_cell_categories} 6 | \usage{ 7 | plot_cell_categories( 8 | spe_object, 9 | categories_of_interest = NULL, 10 | colour_vector = NULL, 11 | feature_colname = "Cell.Type", 12 | cex = 1, 13 | layered = FALSE 14 | ) 15 | } 16 | \arguments{ 17 | \item{spe_object}{SpatialExperiment object in the form of the output of 18 | \code{\link{format_image_to_spe}}.} 19 | 20 | \item{categories_of_interest}{Vector of cell categories to be coloured.} 21 | 22 | \item{colour_vector}{Vector specifying the colours of each cell phenotype.} 23 | 24 | \item{feature_colname}{String specifying the column the cell categories 25 | belong to.} 26 | 27 | \item{cex}{Numeric. The size of the plot points. Default is 1.} 28 | 29 | \item{layered}{Boolean. Whether to plot the cells layer by layer (cell 30 | categories). By default is FALSE.} 31 | } 32 | \value{ 33 | A plot is returned 34 | } 35 | \description{ 36 | Produces a scatter plot of the cells of their x-y positions in 37 | the tissue. Cells are coloured categorically by phenotype. Cells not part 38 | of the phenotypes of interest will be coloured "lightgrey". 39 | } 40 | \examples{ 41 | categories_of_interest <- c("Tumour", "Immune1","Immune2","Immune3") 42 | colour_vector <- c("red","darkblue","blue","darkgreen") 43 | plot_cell_categories(SPIAT::defined_image, categories_of_interest, colour_vector, 44 | feature_colname = "Cell.Type") 45 | } 46 | -------------------------------------------------------------------------------- /man/plot_cell_distances_violin.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/plot_cell_distances_violin.R 3 | \name{plot_cell_distances_violin} 4 | \alias{plot_cell_distances_violin} 5 | \title{plot_cell_distances_violin} 6 | \usage{ 7 | plot_cell_distances_violin(cell_to_cell_dist) 8 | } 9 | \arguments{ 10 | \item{cell_to_cell_dist}{Data.frame containing the distance output between cell types. The 11 | functions that generate the distances can be 12 | \code{\link{calculate_minimum_distances_between_celltypes}} and 13 | \code{\link{calculate_pairwise_distances_between_celltypes}}.} 14 | } 15 | \value{ 16 | A plot is returned 17 | } 18 | \description{ 19 | Plots distances between cells as a violin plot 20 | } 21 | \examples{ 22 | distances <- calculate_pairwise_distances_between_celltypes(SPIAT::defined_image, 23 | cell_types_of_interest = c("Immune1", "Immune2"), feature_colname="Cell.Type") 24 | plot_cell_distances_violin(distances) 25 | } 26 | -------------------------------------------------------------------------------- /man/plot_cell_marker_levels.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/plot_cell_marker_levels.R 3 | \name{plot_cell_marker_levels} 4 | \alias{plot_cell_marker_levels} 5 | \title{plot_cell_marker_levels} 6 | \usage{ 7 | plot_cell_marker_levels(spe_object, marker, feature_colname = "Phenotype") 8 | } 9 | \arguments{ 10 | \item{spe_object}{SpatialExperiment object in the form of the output of 11 | \code{\link{format_image_to_spe}}.} 12 | 13 | \item{marker}{String. Marker to plot.} 14 | 15 | \item{feature_colname}{String. Column containing marker information} 16 | } 17 | \value{ 18 | A plot is returned 19 | } 20 | \description{ 21 | Produces a scatter plot of the level of a marker in each cell. 22 | The level of the marker in all cells is shown, at x-y positions, no matter 23 | if cells are phenotyped as being positive or negative for the particular 24 | marker. 25 | } 26 | \examples{ 27 | plot_cell_marker_levels(SPIAT::simulated_image, "Immune_marker1") 28 | } 29 | -------------------------------------------------------------------------------- /man/plot_cell_percentages.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/plot_cell_percentages.R 3 | \name{plot_cell_percentages} 4 | \alias{plot_cell_percentages} 5 | \title{plot_cell_percentages} 6 | \usage{ 7 | plot_cell_percentages( 8 | cell_proportions, 9 | cells_to_exclude = NULL, 10 | cellprop_colname = "Proportion_name" 11 | ) 12 | } 13 | \arguments{ 14 | \item{cell_proportions}{Data Frame. Output from 15 | \code{\link{calculate_cell_proportions}}.} 16 | 17 | \item{cells_to_exclude}{String Vector. Markers to exclude.} 18 | 19 | \item{cellprop_colname}{String. Column to use for y axis names. Default is 20 | "Proportion_name".} 21 | } 22 | \value{ 23 | A plot is returned 24 | } 25 | \description{ 26 | Plots cells proportions as barplots. 27 | } 28 | \examples{ 29 | p_cells <- calculate_cell_proportions(SPIAT::simulated_image) 30 | plot_cell_percentages(p_cells) 31 | } 32 | -------------------------------------------------------------------------------- /man/plot_composition_heatmap.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/plot_composition_heatmap.R 3 | \name{plot_composition_heatmap} 4 | \alias{plot_composition_heatmap} 5 | \title{plot_composition_heatmap} 6 | \usage{ 7 | plot_composition_heatmap( 8 | composition, 9 | pheno_to_exclude = NULL, 10 | log_values = FALSE, 11 | feature_colname 12 | ) 13 | } 14 | \arguments{ 15 | \item{composition}{Data.frame. Output from 16 | \code{\link{composition_of_neighborhoods}}.} 17 | 18 | \item{pheno_to_exclude}{String Vector of phenotype to exclude.} 19 | 20 | \item{log_values}{Boolean. TRUE if the percentages should be logged (base 21 | 10).} 22 | 23 | \item{feature_colname}{String. Column with cell types.} 24 | } 25 | \value{ 26 | A plot is returned 27 | } 28 | \description{ 29 | Produces a heatmap showing the marker percentages within each 30 | cluster and the cluster sizes. 31 | } 32 | \examples{ 33 | neighborhoods <- identify_neighborhoods(image_no_markers, method = "hierarchical", 34 | min_neighborhood_size = 100, cell_types_of_interest = c("Immune", "Immune1", "Immune2"), 35 | radius = 50, feature_colname = "Cell.Type") 36 | neighborhoods_vis <- composition_of_neighborhoods(neighborhoods, feature_colname="Cell.Type") 37 | plot_composition_heatmap(neighborhoods_vis, feature_colname="Cell.Type") 38 | } 39 | -------------------------------------------------------------------------------- /man/plot_distance_heatmap.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/plot_distance_heatmap.R 3 | \name{plot_distance_heatmap} 4 | \alias{plot_distance_heatmap} 5 | \title{plot_distance_heatmap} 6 | \usage{ 7 | plot_distance_heatmap(phenotype_distances_result, metric = "mean") 8 | } 9 | \arguments{ 10 | \item{phenotype_distances_result}{Dataframe output from 11 | `calculate_summary_distances_between_celltypes` or 12 | `calculate_minimum_distances_between_celltypes`.} 13 | 14 | \item{metric}{Metric to be plotted. One of "mean", "std.dev", "median", "min" 15 | or "max".} 16 | } 17 | \value{ 18 | A plot is returned 19 | } 20 | \description{ 21 | Takes the output of cell_distances and plot the distances as a 22 | heatmap. 23 | } 24 | \examples{ 25 | dists <- calculate_pairwise_distances_between_celltypes(SPIAT::defined_image, 26 | cell_types_of_interest = c("Tumour","Immune1"), feature_colname = "Cell.Type") 27 | summary_distances <- calculate_summary_distances_between_celltypes(dists) 28 | plot_distance_heatmap(summary_distances) 29 | } 30 | -------------------------------------------------------------------------------- /man/plot_marker_level_heatmap.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/plot_marker_level_heatmap.R 3 | \name{plot_marker_level_heatmap} 4 | \alias{plot_marker_level_heatmap} 5 | \title{plot_marker_level_heatmap} 6 | \usage{ 7 | plot_marker_level_heatmap(spe_object, num_splits, marker) 8 | } 9 | \arguments{ 10 | \item{spe_object}{SpatialExperiment object in the form of the output of 11 | \code{\link{format_image_to_spe}}.} 12 | 13 | \item{num_splits}{Integer specifying the blurring level (number of splits) 14 | for the image. Higher numbers result in higher resolution.} 15 | 16 | \item{marker}{String. Marker to plot.} 17 | } 18 | \value{ 19 | A plot is returned 20 | } 21 | \description{ 22 | Blurs the image by splitting the images into small squares. The 23 | marker levels are then averaged within each square. All cells are 24 | considered, regardless of phenotype status. 25 | } 26 | \examples{ 27 | plot_marker_level_heatmap(SPIAT::simulated_image, num_splits = 100, "Tumour_marker") 28 | } 29 | -------------------------------------------------------------------------------- /man/predict_phenotypes.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/predict_phenotypes.R 3 | \name{predict_phenotypes} 4 | \alias{predict_phenotypes} 5 | \title{predict_phenotypes} 6 | \usage{ 7 | predict_phenotypes( 8 | spe_object, 9 | thresholds = NULL, 10 | tumour_marker, 11 | baseline_markers, 12 | nuclear_marker = NULL, 13 | reference_phenotypes = FALSE, 14 | markers_to_phenotype = NULL, 15 | plot_distribution = TRUE 16 | ) 17 | } 18 | \arguments{ 19 | \item{spe_object}{SpatialExperiment object in the form of the output of 20 | \code{\link{format_image_to_spe}}.} 21 | 22 | \item{thresholds}{(Optional) Numeric Vector specifying the cutoff of a 23 | positive reading. The order must match the marker order, and it should be 24 | NA for DAPI.} 25 | 26 | \item{tumour_marker}{String containing the tumour_marker used for the image. 27 | If tumor cells are known, annotate tumor cells as 1 and non-tumor cells as 28 | 0, and include the rowname.} 29 | 30 | \item{baseline_markers}{String Vector. Markers not found on tumour cells to 31 | refine the threshold used for tumour cell phenotying.} 32 | 33 | \item{nuclear_marker}{String. Nuclear marker used.} 34 | 35 | \item{reference_phenotypes}{Boolean. TRUE or FALSE value whether there are reference 36 | phenotypes for the sample obtained by the user through other means (e.g. 37 | HALO or InForm). If there are reference phenotypes available, a matrix of 38 | predicted phenotypes, intensities, and reference phenotypes will be 39 | returned, which can be used as input to "marker_prediction_plot". If no 40 | reference phenotype available, the result of the function will be added to 41 | the spe object used in the input. Note that if a reference phenotype is to 42 | be used, the phenotypes must be an explicit combination of positive markers 43 | (e.g. AMACR,PDL1), as opposed to descriptive (PDL1+ tumour cells).} 44 | 45 | \item{markers_to_phenotype}{String Vector. Markers to be included in the phenotyping. If 46 | NULL, then all markers will be used. DAPI needs to be excluded.} 47 | 48 | \item{plot_distribution}{Boolean. If TRUE, plots of the marker intensities 49 | distributions and cutoffs are plotted.} 50 | } 51 | \value{ 52 | An updated spe object with cell phenotypes or a data.frame of 53 | predicted phenotypes 54 | } 55 | \description{ 56 | Predicts cell phenotypes based on marker intensity levels. If no 57 | prior cell phenotypes are available, it adds the phenotypes to the 58 | SpaitalExperiment object used as input. If reference cell phenotypes are 59 | available, it produces a density plot showing predicted cutoff of a 60 | positive reading for marker intensity and it returns a dataframe containing 61 | the predicted intensity status for a particular marker. 62 | } 63 | \examples{ 64 | # keep the original phenotypes 65 | predicted_result <- predict_phenotypes(spe_object = simulated_image, thresholds = NULL, 66 | tumour_marker = "Tumour_marker",baseline_markers = c("Immune_marker1", "Immune_marker2", 67 | "Immune_marker3", "Immune_marker4"), reference_phenotypes = TRUE) 68 | # update the predicted phenotypes 69 | predicted_spe_image <- predict_phenotypes(spe_object = simulated_image, thresholds = NULL, 70 | tumour_marker = "Tumour_marker",baseline_markers = c("Immune_marker1", "Immune_marker2", 71 | "Immune_marker3", "Immune_marker4"), reference_phenotypes = FALSE) 72 | } 73 | -------------------------------------------------------------------------------- /man/select_celltypes.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/select_celltypes.R 3 | \name{select_celltypes} 4 | \alias{select_celltypes} 5 | \title{select_celltypes} 6 | \usage{ 7 | select_celltypes( 8 | spe_object, 9 | celltypes, 10 | feature_colname = "Phenotype", 11 | keep = TRUE 12 | ) 13 | } 14 | \arguments{ 15 | \item{spe_object}{SpatialExperiment object in the form of the output of 16 | \code{\link{format_image_to_spe}}.} 17 | 18 | \item{celltypes}{String Vector of celltypes of keep or exclude.} 19 | 20 | \item{feature_colname}{String. The column that has the interested cell types. 21 | If the cells ids are used to select cells, use "Cell.ID" for this arg.} 22 | 23 | \item{keep}{Boolean. TRUE if vector of `celltypes` are the cells that are 24 | going to be kept, FALSE if they are to be removed.} 25 | } 26 | \value{ 27 | A SpatialExperiment object is returned. The original image size 28 | and cell count can be accessed by `attr(slim_spe, "original_cell_number")` 29 | and `attr(slim_spe, "range_of_coords")`, where `slim_spe` is the output of 30 | this function. 31 | } 32 | \description{ 33 | Select cell types to keep or exclude in the analysis. The output 34 | of this function also includes the original image size and cell count. 35 | } 36 | \examples{ 37 | data_subset <- select_celltypes(SPIAT::simulated_image, 38 | celltypes = c("Tumour_marker","Immune_marker1","Immune_marker2", 39 | "Immune_marker3","Immune_marker4"), 40 | feature_colname = "Phenotype", keep=TRUE) 41 | attr(data_subset, "original_cell_number") #cell number in the original image 42 | attr(data_subset, "range_of_coords") 43 | dim(data_subset)[2] # this is the new image cell number 44 | } 45 | -------------------------------------------------------------------------------- /man/simulated_image.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/simulated_image.R 3 | \docType{data} 4 | \name{simulated_image} 5 | \alias{simulated_image} 6 | \title{SPE object of a formatted image (simulated by `spaSim` package)} 7 | \format{ 8 | An SpatialExperiment object. Assay contains 5 rows (markers) and 4951 9 | columns (cells); colData contains 4951 rows (cells) and 3 columns. 10 | } 11 | \usage{ 12 | simulated_image 13 | } 14 | \description{ 15 | A dataset that contains a formatted spe object with cell ids and phenotypes 16 | in `colData()` and marker intensities in `assays()`. 17 | } 18 | \seealso{ 19 | \code{\link{defined_image}} \code{\link{image_no_markers}} 20 | } 21 | \keyword{datasets} 22 | -------------------------------------------------------------------------------- /tests/testthat.R: -------------------------------------------------------------------------------- 1 | library(testthat) 2 | library(SPIAT) 3 | 4 | test_check("SPIAT") 5 | -------------------------------------------------------------------------------- /tests/testthat/test-plotting.R: -------------------------------------------------------------------------------- 1 | context("plotting") 2 | 3 | test_that("plot_average_intensity() creates a plot", { 4 | 5 | p <-plot_average_intensity(simulated_image, reference_marker="Immune_marker3", 6 | target_marker="Immune_marker2", 7 | c(30, 35, 40, 45, 50, 75, 100)) 8 | 9 | expect_is(p, "ggplot") 10 | }) 11 | 12 | test_that("plot_cell_categories() creates a plot", { 13 | 14 | phenotypes_of_interest <- c("Tumour", "Immune2") 15 | colour_vector <- c("darkgrey", "blue") 16 | 17 | p <- plot_cell_categories(defined_image, phenotypes_of_interest, 18 | colour_vector,"Cell.Type") 19 | 20 | expect_is(p, "ggplot") 21 | }) 22 | 23 | test_that("plot_cell_distances_violin() creates a plot", { 24 | 25 | pairwise_dist <- calculate_pairwise_distances_between_celltypes( 26 | defined_image, cell_types_of_interest = c("Tumour","Immune1"), 27 | feature_colname = "Cell.Type") 28 | p <- plot_cell_distances_violin(pairwise_dist) 29 | 30 | expect_is(p, "ggplot") 31 | }) 32 | 33 | test_that("plot_cell_percentages() creates a plot", { 34 | 35 | p_cells <- calculate_cell_proportions(simulated_image) 36 | p <- plot_cell_percentages(p_cells) 37 | 38 | expect_is(p, "ggplot") 39 | }) 40 | 41 | test_that("plot_cell_marker_levels() creates a plot", { 42 | 43 | p <- plot_cell_marker_levels(simulated_image, "Immune_marker1") 44 | 45 | expect_is(p, "ggplot") 46 | 47 | }) 48 | 49 | test_that("plot_marker_level_heatmap() creates a plot", { 50 | 51 | p <- plot_marker_level_heatmap(simulated_image, num_splits = 100, 52 | "Tumour_marker") 53 | 54 | expect_is(p, "ggplot") 55 | 56 | }) 57 | 58 | test_that("plot_distance_heatmap() creates a plot", { 59 | pairwise_dist <- calculate_pairwise_distances_between_celltypes( 60 | defined_image, cell_types_of_interest = c("Tumour","Immune1"), 61 | feature_colname = "Cell.Type") 62 | 63 | summary_distances <- 64 | calculate_summary_distances_between_celltypes(pairwise_dist) 65 | p <- plot_distance_heatmap(summary_distances) 66 | 67 | expect_is(p, "ggplot") 68 | 69 | }) 70 | 71 | test_that("marker_intensity_boxplot() creates a plot", { 72 | 73 | p <- marker_intensity_boxplot(simulated_image, "Immune_marker1") 74 | 75 | expect_is(p, "ggplot") 76 | 77 | }) 78 | 79 | test_that("marker_prediction_plot() creates a plot", { 80 | predicted_result <- predict_phenotypes( 81 | spe_object = simulated_image, thresholds = NULL, 82 | tumour_marker = "Tumour_marker", 83 | baseline_markers = c("Immune_marker1", "Immune_marker2", 84 | "Immune_marker3", "Immune_marker4"), 85 | reference_phenotypes = TRUE) 86 | p <- marker_prediction_plot(predicted_result, marker = "Tumour_marker") 87 | expect_is(p, "gtable") 88 | }) 89 | 90 | test_that("marker_surface_plot() creates a plot", { 91 | 92 | p <- marker_surface_plot(simulated_image, num_splits=15, 93 | marker="Immune_marker1") 94 | 95 | expect_is(p, "plotly") 96 | 97 | }) 98 | 99 | test_that("marker_surface_plot_stack() creates a plot", { 100 | 101 | p <- marker_surface_plot_stack( 102 | simulated_image, num_splits=15, 103 | markers=c("Tumour_marker", "Immune_marker4")) 104 | 105 | expect_is(p, "plotly") 106 | }) 107 | 108 | test_that("dimensionality_reduction_plot() creates a plot", { 109 | 110 | p <- dimensionality_reduction_plot(simulated_image, plot_type = "TSNE", 111 | feature_colname = "Phenotype") 112 | 113 | expect_is(p, "ggplot") 114 | }) 115 | 116 | -------------------------------------------------------------------------------- /vignettes/SPIAT-overview.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TrigosTeam/SPIAT/f649d7942abb70fee8c6f630b725033bc5c9524b/vignettes/SPIAT-overview.jpg -------------------------------------------------------------------------------- /vignettes/SPIAT.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Overview of the SPIAT package" 3 | author: "Anna Trigos, Yuzhou Feng, Tianpei Yang, Mabel Li, John Zhu, Volkan Ozcoban, Maria Doyle" 4 | date: "`r BiocStyle::doc_date()`" 5 | output: 6 | BiocStyle::html_document: 7 | self_contained: yes 8 | toc_float: true 9 | toc_depth: 4 10 | package: "`r pkg_ver('SPIAT')`" 11 | bibliography: "`r file.path(system.file(package='SPIAT', 'vignettes'), 'introduction.bib')`" 12 | vignette: > 13 | %\VignetteIndexEntry{Overview of the SPIAT package} 14 | %\VignetteEncoding{UTF-8} 15 | %\VignetteEngine{knitr::rmarkdown} 16 | editor_options: 17 | markdown: 18 | wrap: 72 19 | --- 20 | 21 | ```{r setup, include=FALSE} 22 | knitr::opts_chunk$set( 23 | collapse = TRUE, 24 | comment = "#>", 25 | crop = NULL, 26 | echo = TRUE, fig.width = 3.8, fig.height = 3.8, dpi = 72, out.width = "60%") 27 | ``` 28 | 29 | 30 | # Introduction 31 | 32 | SPIAT (**Sp**atial **I**mage **A**nalysis of **T**issues) is an R 33 | package with a suite of data processing, quality control, visualisation and data 34 | analysis tools. SPIAT is compatible with data 35 | generated from single-cell spatial proteomics platforms (e.g. OPAL, 36 | CODEX, MIBI, cellprofiler). SPIAT reads spatial data in the form of X and Y 37 | coordinates of cells, marker intensities and cell phenotypes. 38 | 39 | SPIAT includes six analysis modules that allow visualisation, 40 | calculation of cell colocalisation, categorisation of the immune 41 | microenvironment relative to tumour areas, analysis of cellular 42 | neighborhoods, and the quantification of spatial heterogeneity, 43 | providing a comprehensive toolkit for spatial data analysis. 44 | 45 | An overview of the functions available is shown in the figure below. 46 | 47 | ```{r, echo=FALSE, fig.height=4.2, fig.width=2.6, fig.align='centre', out.width = "85%"} 48 | knitr::include_graphics("SPIAT-overview.jpg") 49 | ``` 50 | 51 | # You can access the vignettes for other modules of SPIAT here: 52 | 53 | ## [Data reading and formatting](data_reading-formatting.html) 54 | ## [Quality control and visualisation](quality-control_visualisation.html) 55 | ## [Basic analysis](basic_analysis.html) 56 | ## [Cell colocalisation](cell-colocalisation.html) 57 | ## [Spatial heterogeneity](spatial-heterogeneity.html) 58 | ## [Tissue structure](tissue-structure.html) 59 | ## [Cellular neighborhood](neighborhood.html) 60 | 61 | # Installing `SPIAT` 62 | 63 | `r Biocpkg("SPIAT")` is a `R` package available via the 64 | [Bioconductor](http://bioconductor.org) repository for packages. 65 | 66 | ```{r install, eval = FALSE} 67 | if (!requireNamespace("BiocManager", quietly = TRUE)) { 68 | install.packages("BiocManager")} 69 | BiocManager::install("SPIAT") 70 | ``` 71 | 72 | You can also install the latest development version from Github. 73 | 74 | ```{r install_github, eval = FALSE} 75 | if (!requireNamespace("devtools", quietly = TRUE)) { 76 | install.packages("devtools")} 77 | devtools::install_github("TrigosTeam/SPIAT") 78 | ``` 79 | 80 | # Citing `SPIAT` 81 | 82 | We hope that `r Biocpkg("SPIAT")` will be useful for your research. 83 | Please use the following information to cite the package and the overall 84 | approach. Thank you! 85 | 86 | ```{r "citation"} 87 | ## Citation info 88 | citation("SPIAT") 89 | ``` 90 | 91 | 92 | # Author Contributions 93 | 94 | AT, YF, TY, ML, JZ, VO, MD are authors of the package code. MD and YF 95 | wrote the vignette. AT, YF and TY designed the package. 96 | 97 | -------------------------------------------------------------------------------- /vignettes/cross-k-function.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TrigosTeam/SPIAT/f649d7942abb70fee8c6f630b725033bc5c9524b/vignettes/cross-k-function.jpg -------------------------------------------------------------------------------- /vignettes/marker_surface1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TrigosTeam/SPIAT/f649d7942abb70fee8c6f630b725033bc5c9524b/vignettes/marker_surface1.jpg -------------------------------------------------------------------------------- /vignettes/marker_surface2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TrigosTeam/SPIAT/f649d7942abb70fee8c6f630b725033bc5c9524b/vignettes/marker_surface2.jpg -------------------------------------------------------------------------------- /vignettes/tSNE1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TrigosTeam/SPIAT/f649d7942abb70fee8c6f630b725033bc5c9524b/vignettes/tSNE1.jpg -------------------------------------------------------------------------------- /vignettes/tSNE2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TrigosTeam/SPIAT/f649d7942abb70fee8c6f630b725033bc5c9524b/vignettes/tSNE2.jpg -------------------------------------------------------------------------------- /vignettes/tumour-structure.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TrigosTeam/SPIAT/f649d7942abb70fee8c6f630b725033bc5c9524b/vignettes/tumour-structure.jpg --------------------------------------------------------------------------------