Package: hotspotsc
HotspotHotspot is a tool for identifying informative genes (and gene modules) in a single-cell dataset.Importantly 'informative' is decided based on how well a gene's variation agrees with some cell metric - some similarity mapping between cells.Genes which are informative are those whose expression varies in similar way among cells which are nearby in the given metric.The choice of metric allows you to evaluate different types of gene modules:Spatial:  For spatial single-cell datasets, you can define cell similarity by proximity in physical, 2D/3D space.  When set up this way, Hotspot can be used to identifyspatially-varying genes.Lineage:  For single-cell datasets with a lineage tracing system, you can infer a cell developmental lineage and use that as the cell metric.  Then Hotspot can be used to identifyheritable patterns of gene expression.Transcriptional:  The result of a dimensionality reduction procedure can be used create the similarity metric. With this configuration, Hotspot identifies gene modules with local correlation.  This can be particularly useful for interpreting axes of variation in non-linear dimensionality reduction procedures where the mapping between components and genes is not straightforward to evaluate.ExamplesSpatial Data (Mouse Cerebellum)Lineage Data (Mouse Embryogenesis)Human CD4 T cellsOther LinksPublicationbioRxiv PreprintAssociated analysis repoDocumentationInstallationHotspot is installed directly from PyPI using the following command:pip install hotspotscHotspot can be imported asimport hotspotStarting with v1.0, Hotspot uses theAnnDatadata object. If you'd like to use the old version of Hotspot then:pip install hotspotsc==0.9.1The old documentation for that version can be foundhere, but installation will still bepip install hotspotsc==0.9.1.The old initialization for v0.9.1 has now moved tohotspot.Hotspot.legacy_init, see the docs for usage.UsageThe following steps are used when analyzing data in Hotspot:Create the Hotspot objectCompute the KNN graphFind informative genes (by gene autocorrelation)Evaluate pair-wise gene associations (gene local correlations)Group genes into modulesCompute summary per-cell module scoresHere we describe each step in order:Create the Hotspot objectTo start an analysis, first create the hotspot object
When creating the object, you need to specify:The gene counts matrixWhich background model of gene expression to useThe metric space to use to evaluate cell-similarityThe per-cell scaling factorBy default, number of umi per cell is usedFor example:import hotspot
hs = hotspot.Hotspot(
    adata,
    layer_key="counts",
    model='danb',
    latent_obsm_key="X_pca",
    umi_counts_obs_key="total_counts"
)In the example above:adatais aAnnDataobject of cells by geneslayer_keyis the layer ofadatacontaining count informationmodel'danb' selects the umi-adjusted negative binomial modellatent_obsm_keyis the.obsmkey ofadatacontaining Cells x Components matrix (the PCA-reduced space)umi_counts_obs_keyis the.obskey ofadatawith the UMI count for each cellAlternative choices for 'model'The model is used to fit per-cell expectations for each gene assuming no correlations. This is used as the null model when evaluating autocorrelation and gene-gene local correlations.  The choices are:danb: 'Depth-adjusted negative binomial' (aka NBDisp model) fromM3Dropbernoulli: Here only the detection probability for each gene is estimated.  Logistic regression on gene bins is used to evaluate this per-gene and per-cell as a function of the cellsumi_countvalue.normal: Here expression values are assumed to be normally-distributed and scaled by the values inumi_count.none: With this option, the values are assumed to be pre-standardizedChoosing different metricsAbove we usedlatent_obsm_keyas the input option.  This assumes that cells are in an N-dimensional space and similarity between cells is evaluated by computing euclidean distances in this space.  Either the results of a dimensionality reduction or modeling procedure can be input here, or when working with spatial data, the per-cell coordinates.Alternately, instead oflatent_obsm_key, you can specify eithertreeordistances_obsp_key.treeis used for a developmental lineage.  In this form,treeshould be anete3.TreeNodeobject representing the root of a Tree with each cell as its leaves.  This could be constructed programmatically (see ete3's documentation for details) or if your lineage is stored in a Newick file format, you can load it into an ete3.TreeNode object by runningete3.Tree('my_newick.txt').  Note: leaf nodes in the tree must have names that match the column labels in thecountsinput (e.g., cell barcodes).distances_obsp_keyis used to specify cell-cell distances directly.  The value entered should be a Cells x Cells matrix inadata.obsp.Compute the KNN graphThe K-nearest-neighbors graph is computed by running:hs.create_knn_graph(weighted_graph=False, n_neighbors=30)Input options:weighted_graph: bool, whether or not the graph has weights (scaled by cell-cell distances) or is binaryn_neighbors:  the number of neighbors per cell to use. Larger neighborhood sizes can result in more robust detection of correlations and autocorrelations at a cost of missing more fine-grained, smaller-scale patterns and increasing run-timeneighborhood_factor: float, used whenweighted_graph=True.  Weights decay proportionally toexp(-distance^2/distance_N^2)wheredistance_Nis the distance to then_neighbors/neighborhood_factorth neighbor.Generally, the above defaults should be fine in most cases.Find informative genes (by gene autocorrelation)To compute per-gene autocorrelations, run:hs_results = hs.compute_autocorrelations()An optional argument,jobscan be specified to invoke parallel jobs for a speedup on multi-core machines.The output is a pandas DataFrame (and is also saved inhs.results):GeneCZPvalFDRENSG000001396440.06910.5273.21e-267.45e-25ENSG000001792180.07110.5213.43e-267.93e-25ENSG000001961390.08110.5173.59e-268.28e-25ENSG000001198010.06210.5153.68e-268.48e-25ENSG000002333550.05810.5034.15e-269.55e-25...............Columns are:C: Scaled -1:1 autocorrelation coeficientsZ: Z-score for autocorrelationPval:  P-values computed from Z-scoresFDR:  Q-values using the Benjamini-Hochberg procedureEvaluate pair-wise gene associations (gene local correlations)To group genes into modules, we need to first evaluate their pair-wise local correlationsBetter than regular correlations, these 'local' correlations also take into accounts associations where one gene, X, is expression 'near' another gene Y in the map.  This can better resolve correlations between sparsely detected genes.hs_genes = hs_results.loc[hs_results.FDR < 0.05].index # Select genes

local_correlations = hs.compute_local_correlations(hs_genes, jobs=4) # jobs for parallelizationHere we run only on a subset of genes as evaluating all pair-wise correlations is very expensive computationally.   The autocorrelation ordering gives us a natural method to select the informative genes for this purpose.The output is a genes x genes pandas DataFrame of Z-scores for the local correlation values between genes.  The output is also stored inhs.local_correlation_z.Group genes into modulesNow that pair-wise local correlations are calculated, we can group genes into modules.To do this, a convenience method is includedcreate_moduleswhich performs
agglomerative clustering.modules = hs.create_modules(
    min_gene_threshold=30, core_only=True, fdr_threshold=0.05
)A note on the arguments - agglomerative clustering proceeds by joining together genes with the highest pair-wise Z-score with the following caveats:If the FDR-adjusted p-value of the correlation between two branches exceedsfdr_threshold,
then the branches are not merged.If two branches are two be merged and they are both have at leastmin_gene_thresholdgenes,
then the branches are not merged.  Further genes that would join to the resulting merged module
smaller average correlations between genes, i.e. the least-dense module (ifcore_only=False)This method was used to preserved substructure (nested modules) while still giving the analyst
some control. However, since there are a lot of ways to do hierarchical clustering, you can also
manually cluster using the gene-distances inhs.local_correlation_zThe output is a pandas Series that maps gene to module number.  Unassigned genes are indicated with a module number of-1.  The output is also stored inhs.modulesCorrelation modules can be visualized by runninghs.plot_local_correlations():Compute summary per-cell module scoresFinally, summary per-cell scores can be computed for a module.  This is useful for visualizng the general pattern of expression for genes in a module.module_scores = hs.calculate_module_scores()The output is a pandas DataFrame (cells x modules) and is also saved inhs.module_scoresmodule_scores:12345AAACCCAAGGCCTAGA-10.785-2.475-1.407-0.681-1.882AAACCCAGTCGTGCCA-1-5.765.2416.9311.9284.317AAACCCATCGTGCATA-1-2.6193.5720.1431.8321.585AAACGAAGTAATGATG-1-8.7784.0126.9271.1813.882AAACGCTCATGCACTA-12.297-2.517-1.421-1.102-1.547..................These can then be plotted onto other visual representations of the cells.  For example, for spatial modules (from data inRodriques et al, 2019) this looks like: