getNeatOrder sorts already ordinated data by the radial theta angle. This method is useful for organizing data points based on their angular position in a 2D space, typically after an ordination technique such as PCA or NMDS has been applied.

The function takes in a matrix of ordinated data, optionally centers the data using specified methods (mean, median, or NULL), and then calculates the angle (theta) for each point relative to the centroid. The data points are then sorted based on these theta values in ascending order.

One significant application of this sorting method is in plotting heatmaps. By using radial theta sorting, the relationships between data points can be preserved according to the ordination method's spatial configuration, rather than relying on hierarchical clustering, which may distort these relationships. This approach allows for a more faithful representation of the data's intrinsic structure as captured by the ordination process.

getNeatOrder(x, centering = "mean", ...)

# S4 method for class 'matrix'
getNeatOrder(x, centering = "mean", ...)

Arguments

x

A matrix containing the ordinated data to be sorted. Columns should represent the principal components (PCs) and rows should represent the entities being analyzed (e.g. features or samples). There should be 2 columns only representing 2 PCs.

centering

Character scalar. Specifies the method to center the data. Options are "mean", "median", or NULL if your data is already centered. (Default: "mean")

...

Additional arguments passed to other methods.

Value

A character vector of row indices in the sorted order.

Details

It's important to note that the sechm package does actually have the functionality for plotting a heatmap using this radial theta angle ordering, though only by using an MDS ordination.

That being said, the getNeatOrder function is more modular and separate to the plotting, and can be applied to any kind of ordinated data which can be valuable depending on the use case.

Rajaram & Oono (2010) NeatMap - non-clustering heat map alternatives in R outlines this in more detail.

Examples

# Load the required libraries and dataset
library(mia)
library(scater)
#> Loading required package: scuttle
library(ComplexHeatmap)
#> Loading required package: grid
#> 
#> Attaching package: ‘grid’
#> The following object is masked from ‘package:Biostrings’:
#> 
#>     pattern
#> ========================================
#> ComplexHeatmap version 2.22.0
#> Bioconductor page: http://bioconductor.org/packages/ComplexHeatmap/
#> Github page: https://github.com/jokergoo/ComplexHeatmap
#> Documentation: http://jokergoo.github.io/ComplexHeatmap-reference
#> 
#> If you use it in published research, please cite either one:
#> - Gu, Z. Complex Heatmap Visualization. iMeta 2022.
#> - Gu, Z. Complex heatmaps reveal patterns and correlations in multidimensional 
#>     genomic data. Bioinformatics 2016.
#> 
#> 
#> The new InteractiveComplexHeatmap package can directly export static 
#> complex heatmaps into an interactive Shiny app with zero effort. Have a try!
#> 
#> This message can be suppressed by:
#>   suppressPackageStartupMessages(library(ComplexHeatmap))
#> ========================================
library(circlize)
#> ========================================
#> circlize version 0.4.16
#> CRAN page: https://cran.r-project.org/package=circlize
#> Github page: https://github.com/jokergoo/circlize
#> Documentation: https://jokergoo.github.io/circlize_book/book/
#> 
#> If you use it in published research, please cite:
#> Gu, Z. circlize implements and enhances circular visualization
#>   in R. Bioinformatics 2014.
#> 
#> This message can be suppressed by:
#>   suppressPackageStartupMessages(library(circlize))
#> ========================================
data(peerj13075)

# Group data by taxonomic order
tse <- agglomerateByRank(peerj13075, rank = "order", onRankOnly = TRUE)

# Transform the samples into relative abundances using CLR
tse <- transformAssay(
    tse, assay.type = "counts", method="clr", MARGIN = "cols",
    name="clr", pseudocount = TRUE)
#> A pseudocount of 0.5 was applied.

# Transform the features (taxa) into zero mean, unit variance
# (standardize transformation)
tse <- transformAssay(
    tse, assay.type="clr", method="standardize", MARGIN = "rows")

# Perform PCA using calculatePCA
res <- calculatePCA(tse, assay.type = "standardize", ncomponents = 10)

# Sort by radial theta and sort the original assay data
sorted_order <- getNeatOrder(res[, c(1,2)], centering = "mean")
tse <- tse[, sorted_order]

# Define the color function and cap the colors at [-5, 5]
col_fun <- colorRamp2(c(-5, 0, 5), c("blue", "white", "red"))

# Create the heatmap
heatmap <- Heatmap(assay(tse, "standardize"),
              name = "NeatMap",
              col = col_fun,
              cluster_rows = FALSE,  # Do not cluster rows
              cluster_columns = FALSE,  # Do not cluster columns
              show_row_dend = FALSE,
              show_column_dend = FALSE,
              row_names_gp = gpar(fontsize = 4), 
              column_names_gp = gpar(fontsize = 6), 
              heatmap_width = unit(20, "cm"),  
              heatmap_height = unit(15, "cm")  
)