exprmat 0.1.13__tar.gz → 0.1.15__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {exprmat-0.1.13 → exprmat-0.1.15}/PKG-INFO +4 -1
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/__init__.py +1 -1
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/ansi.py +12 -30
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/finders.py +1 -1
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/hsa/mapping-ensembl.pkl +0 -0
- exprmat-0.1.15/exprmat/data/mmu/genome.tsv.gz +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/mmu/mapping-ensembl.pkl +0 -0
- exprmat-0.1.15/exprmat/data/mmu/mapping-name.pkl +0 -0
- exprmat-0.1.15/exprmat/data/presets.py +44 -0
- exprmat-0.1.15/exprmat/dynamics/__init__.py +51 -0
- exprmat-0.1.15/exprmat/dynamics/generank.py +372 -0
- exprmat-0.1.15/exprmat/dynamics/linreg.py +144 -0
- exprmat-0.1.15/exprmat/dynamics/moments.py +106 -0
- exprmat-0.1.15/exprmat/dynamics/optimization.py +202 -0
- exprmat-0.1.15/exprmat/dynamics/parallel.py +148 -0
- exprmat-0.1.15/exprmat/dynamics/preprocess.py +337 -0
- exprmat-0.1.15/exprmat/dynamics/pseudotime.py +459 -0
- exprmat-0.1.15/exprmat/dynamics/transition.py +231 -0
- exprmat-0.1.15/exprmat/dynamics/utils.py +617 -0
- exprmat-0.1.15/exprmat/dynamics/velocity.py +1145 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/plotting/summary.py +14 -13
- exprmat-0.1.15/exprmat/plotting/utils.py +1 -0
- exprmat-0.1.15/exprmat/plotting/velocity.py +595 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/reader/experiment.py +317 -41
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/reader/matcher.py +246 -7
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/reduction/mde.py +39 -2
- exprmat-0.1.15/exprmat/reduction/outliers.py +185 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/reduction/plot.py +31 -10
- exprmat-0.1.15/exprmat/transfer/__init__.py +0 -0
- exprmat-0.1.15/exprmat/transfer/atlas.py +233 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat.egg-info/PKG-INFO +4 -1
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat.egg-info/SOURCES.txt +18 -2
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat.egg-info/requires.txt +3 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/setup.py +5 -2
- exprmat-0.1.13/exprmat/data/mmu/genome.tsv.gz +0 -0
- exprmat-0.1.13/exprmat/data/mmu/mapping-name.pkl +0 -0
- exprmat-0.1.13/exprmat/reduction/pumap.py +0 -593
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/clustering/__init__.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/clustering/leiden.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/clustering/rogue.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/clustering/spectral.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/clustering/utils.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/cnv/__init__.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/cnv/cnvscore.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/cnv/infercnv.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/configuration.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/__init__.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/delim.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/geneset.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/gff.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/hsa/entrez.tsv.gz +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/hsa/genesets/all.gmt +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/hsa/genesets/bp.gmt +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/hsa/genesets/cancer-modules.gmt +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/hsa/genesets/cancer-neighborhoods.gmt +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/hsa/genesets/cancer.gmt +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/hsa/genesets/cc.gmt +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/hsa/genesets/chemical-perturb.gmt +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/hsa/genesets/hallmark.gmt +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/hsa/genesets/human-phenotype-ontology.gmt +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/hsa/genesets/immune-perturb.gmt +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/hsa/genesets/kegg.gmt +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/hsa/genesets/mf.gmt +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/hsa/genesets/microrna.gmt +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/hsa/genesets/oncogenic.gmt +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/hsa/genesets/pathways.gmt +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/hsa/genesets/positional.gmt +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/hsa/genesets/single-cell.gmt +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/hsa/genesets/transcript-factors.gmt +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/hsa/genesets/vaccine.gmt +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/hsa/genome.tsv.gz +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/hsa/lr/baccin2019 +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/hsa/lr/cellcall +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/hsa/lr/cellchatdb +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/hsa/lr/cellinker +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/hsa/lr/cellphonedb +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/hsa/lr/celltalkdb +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/hsa/lr/connectomedb2020 +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/hsa/lr/consensus +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/hsa/lr/embrace +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/hsa/lr/guide2pharma +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/hsa/lr/hpmr +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/hsa/lr/icellnet +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/hsa/lr/italk +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/hsa/lr/kirouac2010 +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/hsa/lr/lrdb +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/hsa/lr/ramilowski2015 +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/hsa/mapping-name.pkl +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/hsa/orthologs/aca.tsv.gz +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/hsa/orthologs/bta.tsv.gz +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/hsa/orthologs/cel.tsv.gz +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/hsa/orthologs/clu.tsv.gz +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/hsa/orthologs/dme.tsv.gz +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/hsa/orthologs/dre.tsv.gz +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/hsa/orthologs/eca.tsv.gz +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/hsa/orthologs/fca.tsv.gz +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/hsa/orthologs/gga.tsv.gz +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/hsa/orthologs/mdo.tsv.gz +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/hsa/orthologs/mmu.tsv.gz +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/hsa/orthologs/mmul.gz +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/hsa/orthologs/oan.tsv.gz +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/hsa/orthologs/ptr.tsv.gz +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/hsa/orthologs/rno.tsv.gz +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/hsa/orthologs/sce.tsv.gz +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/hsa/orthologs/spo.tsv.gz +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/hsa/orthologs/ssc.tsv.gz +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/hsa/orthologs/xla.tsv.gz +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/hsa/taxa +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/lr.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/mmu/entrez.tsv.gz +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/mmu/genesets/all.gmt +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/mmu/genesets/azimuth.gmt +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/mmu/genesets/biocarta.gmt +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/mmu/genesets/bp.gmt +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/mmu/genesets/cc.gmt +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/mmu/genesets/chemical-perturb.gmt +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/mmu/genesets/hallmark.gmt +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/mmu/genesets/kegg.gmt +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/mmu/genesets/m2.gmt +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/mmu/genesets/markers.gmt +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/mmu/genesets/mf.gmt +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/mmu/genesets/microrna.gmt +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/mmu/genesets/mpt.gmt +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/mmu/genesets/positional.gmt +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/mmu/genesets/reactome.gmt +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/mmu/genesets/transcript-factors.gmt +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/mmu/genesets/wikipathway.gmt +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/mmu/lr/consensus +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/mmu/taxa +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/private.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/data/ranges.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/descriptive/__init__.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/descriptive/aggregate.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/descriptive/de.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/descriptive/gse.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/descriptive/kde.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/descriptive/summary.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/descriptive/tcr.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/lr/__init__.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/lr/aggregate.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/lr/method.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/lr/methods/__init__.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/lr/methods/cellchat.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/lr/methods/cellphonedb.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/lr/methods/connectome.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/lr/methods/geomean.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/lr/methods/logfc.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/lr/methods/natmi.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/lr/methods/rank_aggregate.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/lr/methods/scseqcomm.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/lr/methods/singlecellsignalr.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/lr/pipeline.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/lr/preprocess.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/lr/resources.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/lr/utils.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/plotting/__init__.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/plotting/cnv.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/plotting/de.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/plotting/expression.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/plotting/gse.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/plotting/lr.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/plotting/palettes.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/plotting/sankey.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/preprocessing/__init__.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/preprocessing/doublets/__init__.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/preprocessing/doublets/composite.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/preprocessing/doublets/scrublet.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/preprocessing/filter.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/preprocessing/integrate.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/preprocessing/linear.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/preprocessing/normal.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/preprocessing/plot.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/preprocessing/qc.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/preprocessing/sctransform/__init__.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/preprocessing/sctransform/estimate.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/preprocessing/sctransform/ksmooth.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/preprocessing/sctransform/residual.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/preprocessing/sctransform/transform.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/preprocessing/sparse.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/preprocessing/uniform.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/reader/__init__.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/reader/metadata.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/reduction/__init__.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/reduction/forceatlas.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/reduction/nn.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/reduction/pca.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/reduction/tsne.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/reduction/umap.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat/utils.py +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat.egg-info/dependency_links.txt +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat.egg-info/not-zip-safe +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/exprmat.egg-info/top_level.txt +0 -0
- {exprmat-0.1.13 → exprmat-0.1.15}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: exprmat
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.15
|
|
4
4
|
Summary: routines to process expression matrices
|
|
5
5
|
Home-page: https://github.com/yang-z-03/exprmat
|
|
6
6
|
Author: Zheng Yang
|
|
@@ -31,6 +31,9 @@ Requires-Dist: gseapy
|
|
|
31
31
|
Requires-Dist: metacells
|
|
32
32
|
Requires-Dist: sh
|
|
33
33
|
Requires-Dist: networkx
|
|
34
|
+
Requires-Dist: palantir
|
|
35
|
+
Requires-Dist: scfates
|
|
36
|
+
Requires-Dist: rich
|
|
34
37
|
Dynamic: author
|
|
35
38
|
Dynamic: author-email
|
|
36
39
|
Dynamic: home-page
|
|
@@ -1,17 +1,8 @@
|
|
|
1
1
|
|
|
2
|
-
# ./shared/ansi.py:
|
|
3
|
-
# provides basic ansi console coloring and cursor manipulation support.
|
|
4
|
-
# considering adding later another alternative implementation of the same
|
|
5
|
-
# interface for terminal/emulators that do not support ansi.
|
|
6
|
-
#
|
|
7
|
-
# license: gplv3. <https://www.gnu.org/licenses>
|
|
8
|
-
# contact: yang-z <xornent at outlook dot com>
|
|
9
|
-
|
|
10
2
|
import re
|
|
11
3
|
import os
|
|
12
4
|
import sys
|
|
13
5
|
|
|
14
|
-
# foregrounds -----------------------------------------------------------------
|
|
15
6
|
|
|
16
7
|
def fore_black() -> None:
|
|
17
8
|
print('\033[30m', end = '')
|
|
@@ -40,13 +31,11 @@ def fore_white() -> None:
|
|
|
40
31
|
def fore_gray() -> None:
|
|
41
32
|
print('\033[8m', end = '')
|
|
42
33
|
|
|
43
|
-
|
|
44
|
-
|
|
34
|
+
|
|
45
35
|
def ansi_reset() -> None:
|
|
46
36
|
print('\033[0m', end = '')
|
|
47
37
|
|
|
48
|
-
|
|
49
|
-
|
|
38
|
+
|
|
50
39
|
def back_black() -> None:
|
|
51
40
|
print('\033[40m', end = '')
|
|
52
41
|
|
|
@@ -71,7 +60,6 @@ def back_cyan() -> None:
|
|
|
71
60
|
def back_white() -> None:
|
|
72
61
|
print('\033[47m', end = '')
|
|
73
62
|
|
|
74
|
-
# cursor operations
|
|
75
63
|
|
|
76
64
|
def ansi_move_cursor(line: int, col: int) -> None:
|
|
77
65
|
if line == 0: pass
|
|
@@ -82,8 +70,6 @@ def ansi_move_cursor(line: int, col: int) -> None:
|
|
|
82
70
|
elif col > 0: print('\033[{0}C'.format(str(col)), end = '', flush = True) # moves right
|
|
83
71
|
elif col < 0: print('\033[{0}D'.format(str(-col)), end = '', flush = True) # moves left
|
|
84
72
|
|
|
85
|
-
def fill_blank(blanks: int) -> None:
|
|
86
|
-
print(' ' * blanks, end = '', flush = True)
|
|
87
73
|
|
|
88
74
|
def common_length(string: str, limit: int) -> str:
|
|
89
75
|
|
|
@@ -109,34 +95,27 @@ def common_length(string: str, limit: int) -> str:
|
|
|
109
95
|
|
|
110
96
|
else: return ('{:<' + str(limit - cn_length) + '}').format(string)
|
|
111
97
|
|
|
98
|
+
|
|
112
99
|
def fill_blank(blanks: int, string: str) -> None:
|
|
113
100
|
print(common_length(string, blanks), end = '', flush = True)
|
|
114
101
|
|
|
115
|
-
def line_start() -> None:
|
|
116
|
-
print('\r', end = '')
|
|
117
102
|
|
|
118
|
-
def print_message(color, title, path, overwrite = True):
|
|
119
|
-
if overwrite:
|
|
120
|
-
print('\r{0}[{1}]\033[0m'.format(color, title), common_length(path, 70), end = '')
|
|
121
|
-
return '{0}[{1}]\033[0m'.format(color, title) + ' ' + common_length(path, 70)
|
|
122
|
-
else:
|
|
123
|
-
print('{0}[{1}]\033[0m'.format(color, title), common_length(path, 70))
|
|
124
|
-
return '{0}[{1}]\033[0m'.format(color, title) + ' ' + common_length(path, 70)
|
|
125
|
-
|
|
126
103
|
def format_file_size(size):
|
|
127
104
|
for suffix in ['B', 'KiB', 'MiB', 'GiB', 'TiB']:
|
|
128
105
|
if size < 1024.0 or suffix == 'TiB': break
|
|
129
106
|
size /= 1024.0
|
|
130
107
|
return f"{size:.2f} {suffix}"
|
|
131
108
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
def error(text: str) -> None:
|
|
109
|
+
|
|
110
|
+
def error(text: str, error = None) -> None:
|
|
135
111
|
fore_red()
|
|
136
112
|
print('[error]', end = ' ')
|
|
137
113
|
ansi_reset()
|
|
138
114
|
print(text)
|
|
139
|
-
|
|
115
|
+
|
|
116
|
+
if error is None: raise Exception(text)
|
|
117
|
+
else: raise Exception(text) from error
|
|
118
|
+
|
|
140
119
|
|
|
141
120
|
def warning(text: str) -> None:
|
|
142
121
|
fore_yellow()
|
|
@@ -145,6 +124,7 @@ def warning(text: str) -> None:
|
|
|
145
124
|
print(text)
|
|
146
125
|
ansi_reset()
|
|
147
126
|
|
|
127
|
+
|
|
148
128
|
def info(text: str) -> None:
|
|
149
129
|
fore_cyan()
|
|
150
130
|
print('[i]', end = ' ')
|
|
@@ -152,6 +132,7 @@ def info(text: str) -> None:
|
|
|
152
132
|
print(text)
|
|
153
133
|
ansi_reset()
|
|
154
134
|
|
|
135
|
+
|
|
155
136
|
def clear():
|
|
156
137
|
# for windows
|
|
157
138
|
if os.name == 'nt':
|
|
@@ -160,6 +141,7 @@ def clear():
|
|
|
160
141
|
# for mac and linux(here, os.name is 'posix')
|
|
161
142
|
else: os.system('clear')
|
|
162
143
|
|
|
144
|
+
|
|
163
145
|
def red(x): return '\033[31m' + x + '\033[0m'
|
|
164
146
|
def green(x): return '\033[32m' + x + '\033[0m'
|
|
165
147
|
def yellow(x): return '\033[33m' + x + '\033[0m'
|
|
@@ -31,7 +31,7 @@ def get_genome(taxa):
|
|
|
31
31
|
genome[taxa]['genes'] = pandas.read_table(
|
|
32
32
|
os.path.join(basepath, f'{taxa}', 'genome.tsv.gz'),
|
|
33
33
|
# set low memory to false to allow correct adjustment to mixed dtype.
|
|
34
|
-
index_col = '.ugene', dtype = {'.seqid': str}
|
|
34
|
+
index_col = '.ugene', dtype = {'.seqid': str}, low_memory = False
|
|
35
35
|
)
|
|
36
36
|
|
|
37
37
|
return genome[taxa]['genes']
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
|
|
2
|
+
s_gene_sets = {
|
|
3
|
+
'mmu': [ # the original list
|
|
4
|
+
'Atad2', 'Blm', 'Brip1', 'Casp8ap2', 'Ccne2', 'Cdc45', 'Cdc6', 'Cdca7',
|
|
5
|
+
'Chaf1b', 'Clspn', 'Dscc1', 'Dtl', 'E2f8', 'Exo1', 'Fen1', 'Gins2', 'Gmnn',
|
|
6
|
+
'Hells', 'Mcm2', 'Mcm4', 'Mcm5', 'Mcm6', 'Msh2', 'Nasp', 'Pcna', 'Pola1',
|
|
7
|
+
'Pold3', 'Prim1', 'Rad51', 'Rad51ap1', 'Rfc2', 'Rpa2', 'Rrm1', 'Rrm2',
|
|
8
|
+
'Slbp', 'Tipin', 'Tyms', 'Ubr7', 'Uhrf1', 'Ung', 'Usp1', 'Wdr76'
|
|
9
|
+
],
|
|
10
|
+
'hsa': [ # translated from mice
|
|
11
|
+
'MCM5', 'PCNA', 'TYMS', 'FEN1', 'MCM2', 'MCM4', 'RRM1', 'UNG', 'GINS2',
|
|
12
|
+
'MCM6', 'CDCA7', 'DTL', 'PRIM1', 'UHRF1', 'MLF1IP', 'HELLS', 'RFC2',
|
|
13
|
+
'RPA2', 'NASP', 'RAD51AP1', 'GMNN', 'WDR76', 'SLBP', 'CCNE2', 'UBR7',
|
|
14
|
+
'POLD3', 'MSH2', 'ATAD2', 'RAD51', 'RRM2', 'CDC45', 'CDC6', 'EXO1',
|
|
15
|
+
'TIPIN', 'DSCC1', 'BLM', 'CASP8AP2', 'USP1', 'CLSPN', 'POLA1', 'CHAF1B',
|
|
16
|
+
'BRIP1', 'E2F8'
|
|
17
|
+
]
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
g2m_genesets = {
|
|
21
|
+
'mmu': [
|
|
22
|
+
'Anln', 'Anp32e', 'Aurka', 'Aurkb', 'Birc5', 'Bub1', 'Cbx5', 'Ccnb2',
|
|
23
|
+
'Cdc20', 'Cdc25c', 'Cdca2', 'Cdca3', 'Cdca8', 'Cdk1', 'Cenpa', 'Cenpe',
|
|
24
|
+
'Cenpf', 'Ckap2', 'Ckap2l', 'Ckap5', 'Cks1b', 'Cks2', 'Ctcf', 'Dlgap5',
|
|
25
|
+
'Ect2', 'G2e3', 'Gas2l3', 'Gtse1', 'Hjurp', 'Hmgb2', 'Hmmr', 'Kif11',
|
|
26
|
+
'Kif20b', 'Kif23', 'Kif2c', 'Lbr', 'Mki67', 'Ncapd2', 'Ndc80', 'Nek2',
|
|
27
|
+
'Nuf2', 'Nusap1', 'Psrc1', 'Rangap1', 'Smc4', 'Tacc3', 'Tmpo', 'Top2a',
|
|
28
|
+
'Tpx2', 'Ttk', 'Tubb4b', 'Ube2c'
|
|
29
|
+
],
|
|
30
|
+
'hsa': [
|
|
31
|
+
'HMGB2', 'CDK1', 'NUSAP1', 'UBE2C', 'BIRC5', 'TPX2', 'TOP2A', 'NDC80',
|
|
32
|
+
'CKS2', 'NUF2', 'CKS1B', 'MKI67', 'TMPO', 'CENPF', 'TACC3', 'FAM64A',
|
|
33
|
+
'SMC4', 'CCNB2', 'CKAP2L', 'CKAP2', 'AURKB', 'BUB1', 'KIF11', 'ANP32E',
|
|
34
|
+
'TUBB4B', 'GTSE1', 'KIF20B', 'HJURP', 'CDCA3', 'HN1', 'CDC20', 'TTK',
|
|
35
|
+
'CDC25C', 'KIF2C', 'RANGAP1', 'NCAPD2', 'DLGAP5', 'CDCA2', 'CDCA8',
|
|
36
|
+
'ECT2', 'KIF23', 'HMMR', 'AURKA', 'PSRC1', 'ANLN', 'LBR', 'CKAP5', 'CENPE',
|
|
37
|
+
'CTCF', 'NEK2', 'G2E3', 'GAS2L3', 'CBX5', 'CENPA'
|
|
38
|
+
]
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
preset_genesets = {
|
|
42
|
+
's': s_gene_sets,
|
|
43
|
+
'g2m': g2m_genesets
|
|
44
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
|
|
2
|
+
from exprmat.dynamics.preprocess import filter_and_normalize
|
|
3
|
+
from exprmat.dynamics.pseudotime import velocity_pseudotime, terminal_states
|
|
4
|
+
from exprmat.dynamics.transition import transition_matrix
|
|
5
|
+
from exprmat.dynamics.moments import moments
|
|
6
|
+
from exprmat.dynamics.velocity import velocity, velocity_confidence, velocity_embedding, velocity_graph
|
|
7
|
+
from exprmat.dynamics.generank import rank_velocity_genes
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def run_velocity(
|
|
11
|
+
adata,
|
|
12
|
+
neighbor_key = 'neighbors', neighbor_connectivity = 'connectivities', n_neighbors = 35,
|
|
13
|
+
hvg = 'vst.norm',
|
|
14
|
+
velocity_key = 'velocity',
|
|
15
|
+
n_cpus = None,
|
|
16
|
+
kwargs_filter = { 'enforce': False },
|
|
17
|
+
kwargs_velocity = {},
|
|
18
|
+
kwargs_velocity_graph = {},
|
|
19
|
+
kwargs_terminal_state = {},
|
|
20
|
+
kwargs_pseudotime = { 'save_diffmap': True },
|
|
21
|
+
):
|
|
22
|
+
if (
|
|
23
|
+
('spliced.counts' not in adata.layers.keys()) and
|
|
24
|
+
('unspliced.counts' not in adata.layers.keys())
|
|
25
|
+
):
|
|
26
|
+
filter_and_normalize(adata, **kwargs_filter)
|
|
27
|
+
|
|
28
|
+
moments(adata, neighbor_key = neighbor_key, mode = neighbor_connectivity)
|
|
29
|
+
|
|
30
|
+
velocity(
|
|
31
|
+
adata,
|
|
32
|
+
vkey = velocity_key,
|
|
33
|
+
use_highly_variable = hvg,
|
|
34
|
+
neighbor_key = neighbor_key,
|
|
35
|
+
**kwargs_velocity
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
velocity_graph(
|
|
39
|
+
adata,
|
|
40
|
+
n_jobs = n_cpus,
|
|
41
|
+
vkey = velocity_key,
|
|
42
|
+
neighbor_key = neighbor_key,
|
|
43
|
+
mode_neighbors = neighbor_connectivity,
|
|
44
|
+
n_neighbors = n_neighbors,
|
|
45
|
+
**kwargs_velocity_graph
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
terminal_states(adata, vkey = velocity_key, neighbor_key = neighbor_key, **kwargs_terminal_state)
|
|
49
|
+
velocity_pseudotime(adata, vkey = velocity_key, neighbor_key = neighbor_key, **kwargs_pseudotime)
|
|
50
|
+
velocity_confidence(adata, vkey = velocity_key, neighbor_key = neighbor_key)
|
|
51
|
+
|
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
|
|
2
|
+
import numpy as np
|
|
3
|
+
from scipy.sparse import issparse
|
|
4
|
+
from exprmat.ansi import error, warning, info
|
|
5
|
+
|
|
6
|
+
from exprmat.dynamics.utils import strings_to_categoricals, vcorrcoef
|
|
7
|
+
from exprmat.dynamics.pseudotime import velocity_pseudotime
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def get_mean_var(X, ignore_zeros = False, perc = None):
|
|
11
|
+
|
|
12
|
+
data = X.data if issparse(X) else X
|
|
13
|
+
mask_nans = np.isnan(data) | np.isinf(data) | np.isneginf(data)
|
|
14
|
+
|
|
15
|
+
if issparse(X):
|
|
16
|
+
n_nonzeros = X.getnnz(axis=0)
|
|
17
|
+
else:
|
|
18
|
+
n_nonzeros = (X != 0).sum(axis=0)
|
|
19
|
+
|
|
20
|
+
if ignore_zeros:
|
|
21
|
+
n_counts = n_nonzeros
|
|
22
|
+
else:
|
|
23
|
+
n_counts = X.shape[0]
|
|
24
|
+
|
|
25
|
+
if mask_nans.sum() > 0:
|
|
26
|
+
if issparse(X):
|
|
27
|
+
data[mask_nans] = 0
|
|
28
|
+
n_nans = (n_nonzeros - (X != 0).sum(0)).A1
|
|
29
|
+
else:
|
|
30
|
+
X[mask_nans] = 0
|
|
31
|
+
n_nans = mask_nans.sum(0)
|
|
32
|
+
n_counts -= n_nans
|
|
33
|
+
|
|
34
|
+
if perc is not None:
|
|
35
|
+
if np.size(perc) < 2:
|
|
36
|
+
perc = [perc, 100] if perc < 50 else [0, perc]
|
|
37
|
+
lb, ub = np.percentile(data, perc)
|
|
38
|
+
if issparse(X):
|
|
39
|
+
X.data = np.clip(data, lb, ub)
|
|
40
|
+
else:
|
|
41
|
+
X = np.clip(data, lb, ub)
|
|
42
|
+
|
|
43
|
+
if issparse(X):
|
|
44
|
+
mean = (X.sum(0) / n_counts).A1
|
|
45
|
+
mean_sq = (X.multiply(X).sum(0) / n_counts).A1
|
|
46
|
+
else:
|
|
47
|
+
mean = X.sum(0) / n_counts
|
|
48
|
+
mean_sq = np.multiply(X, X).sum(0) / n_counts
|
|
49
|
+
|
|
50
|
+
n_counts = np.clip(n_counts, 2, None) # to avoid division by zero
|
|
51
|
+
var = (mean_sq - mean**2) * (n_counts / (n_counts - 1))
|
|
52
|
+
|
|
53
|
+
mean = np.nan_to_num(mean)
|
|
54
|
+
var = np.nan_to_num(var)
|
|
55
|
+
|
|
56
|
+
return mean, var
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def select_groups(adata, groups = "all", key = "leiden"):
|
|
60
|
+
|
|
61
|
+
strings_to_categoricals(adata)
|
|
62
|
+
if isinstance(groups, list) and isinstance(groups[0], int):
|
|
63
|
+
groups = [f"{n}" for n in groups]
|
|
64
|
+
categories = adata.obs[key].cat.categories
|
|
65
|
+
groups_masks = np.array([
|
|
66
|
+
categories[i] == adata.obs[key].values
|
|
67
|
+
for i, name in enumerate(categories)
|
|
68
|
+
])
|
|
69
|
+
|
|
70
|
+
if groups == "all":
|
|
71
|
+
groups = categories.values
|
|
72
|
+
else:
|
|
73
|
+
groups_ids = [categories.get_loc(name) for name in groups]
|
|
74
|
+
groups_masks = groups_masks[groups_ids]
|
|
75
|
+
groups = categories[groups_ids].values
|
|
76
|
+
|
|
77
|
+
return groups, groups_masks
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def velocity_clusters(
|
|
81
|
+
adata,
|
|
82
|
+
vkey = "velocity",
|
|
83
|
+
match_with = "clusters",
|
|
84
|
+
neighbor_key = 'neighbors',
|
|
85
|
+
highly_variable = 'hvg.vst',
|
|
86
|
+
disp_norm = 'disp.norm',
|
|
87
|
+
likelihood = 'fit.likelihood',
|
|
88
|
+
sort_by = "velocity.pseudotime",
|
|
89
|
+
resolution = None,
|
|
90
|
+
min_likelihood = None
|
|
91
|
+
):
|
|
92
|
+
"""
|
|
93
|
+
Computes velocity clusters via louvain on velocities.
|
|
94
|
+
|
|
95
|
+
Parameters
|
|
96
|
+
----------
|
|
97
|
+
data : anndata.AnnData
|
|
98
|
+
Annotated data matrix.
|
|
99
|
+
|
|
100
|
+
vkey: str (default: `'velocity'`)
|
|
101
|
+
Key of velocities computed in `tl.velocity`
|
|
102
|
+
|
|
103
|
+
match_with : int, optional (default: 100)
|
|
104
|
+
The number of genes that appear in the returned tables.
|
|
105
|
+
|
|
106
|
+
match_with: str (default: `'clusters'`)
|
|
107
|
+
Match the names of the velocity clusters with the names of this key (.obs).
|
|
108
|
+
|
|
109
|
+
sort_by: str or None (default: `'dpt_pseudotime'`)
|
|
110
|
+
Sort velocity clusters by this key (.obs).
|
|
111
|
+
|
|
112
|
+
resolution: float (default: 0.7)
|
|
113
|
+
Resolution for louvain modularity.
|
|
114
|
+
|
|
115
|
+
min_likelihood: float between `0` and `1` or `None` (default: `None`)
|
|
116
|
+
Only rank velocity of genes with a likelihood higher than min_likelihood.
|
|
117
|
+
|
|
118
|
+
Returns
|
|
119
|
+
-------
|
|
120
|
+
velocity_clusters : `.obs`
|
|
121
|
+
Clusters obtained from applying louvain modularity on velocity expression.
|
|
122
|
+
"""
|
|
123
|
+
|
|
124
|
+
tmp_filter = ~ np.isnan(adata.layers[vkey].sum(0))
|
|
125
|
+
if f"{vkey}.genes" in adata.var.keys():
|
|
126
|
+
tmp_filter &= np.array(adata.var[f"{vkey}.genes"].values, dtype = bool)
|
|
127
|
+
|
|
128
|
+
if "unspliced" in adata.layers.keys():
|
|
129
|
+
n_counts = (adata.layers["unspliced"] > 0).sum(0)
|
|
130
|
+
n_counts = n_counts.A1 if issparse(adata.layers["unspliced"]) else n_counts
|
|
131
|
+
min_counts = min(50, np.percentile(n_counts, 50))
|
|
132
|
+
tmp_filter &= np.ravel(n_counts > min_counts)
|
|
133
|
+
|
|
134
|
+
if f"{vkey}.r2" in adata.var.keys():
|
|
135
|
+
r2 = adata.var[f"{vkey}.r2"]
|
|
136
|
+
min_r2 = np.percentile(r2[r2 > 0], 50)
|
|
137
|
+
tmp_filter &= r2 > min_r2
|
|
138
|
+
|
|
139
|
+
if disp_norm in adata.var.keys():
|
|
140
|
+
dispersions = adata.var[disp_norm]
|
|
141
|
+
min_dispersion = np.percentile(dispersions, 20)
|
|
142
|
+
tmp_filter &= dispersions > min_dispersion
|
|
143
|
+
|
|
144
|
+
if likelihood in adata.var.keys() and min_likelihood is not None:
|
|
145
|
+
tmp_filter &= adata.var[likelihood] > min_likelihood
|
|
146
|
+
|
|
147
|
+
from anndata import AnnData
|
|
148
|
+
vdata = AnnData(adata.layers[vkey][:, tmp_filter])
|
|
149
|
+
vdata.obs = adata.obs.copy()
|
|
150
|
+
vdata.var = adata.var[tmp_filter].copy()
|
|
151
|
+
|
|
152
|
+
if highly_variable in vdata.var.keys():
|
|
153
|
+
vdata.var[highly_variable] = np.array(
|
|
154
|
+
vdata.var[highly_variable], dtype = bool)
|
|
155
|
+
|
|
156
|
+
import scanpy as sc
|
|
157
|
+
|
|
158
|
+
sc.pp.pca(vdata, n_comps = 20, svd_solver = "arpack")
|
|
159
|
+
sc.pp.neighbors(vdata, n_pcs = 20)
|
|
160
|
+
sc.tl.leiden(vdata, resolution = 0.7 if resolution is None else resolution)
|
|
161
|
+
|
|
162
|
+
if sort_by == "velocity.pseudotime" and sort_by not in adata.obs.keys():
|
|
163
|
+
velocity_pseudotime(adata, vkey = vkey, neighbor_key = neighbor_key)
|
|
164
|
+
|
|
165
|
+
if sort_by in vdata.obs.keys():
|
|
166
|
+
vc = vdata.obs["leiden"]
|
|
167
|
+
vc_cats = vc.cat.categories
|
|
168
|
+
mean_times = [np.mean(vdata.obs[sort_by][vc == cat]) for cat in vc_cats]
|
|
169
|
+
vdata.obs["leiden"] = vdata.obs["leiden"].cat.reorder_categories(
|
|
170
|
+
vc_cats[np.argsort(mean_times)])
|
|
171
|
+
|
|
172
|
+
if isinstance(match_with, str) and match_with in adata.obs.keys():
|
|
173
|
+
from .utils import most_common_in_list
|
|
174
|
+
vc = vdata.obs["leiden"]
|
|
175
|
+
cats_nums = {cat: 0 for cat in adata.obs[match_with].cat.categories}
|
|
176
|
+
for cat in vc.cat.categories:
|
|
177
|
+
cells_in_cat = np.where(vc == cat)[0]
|
|
178
|
+
new_cat = most_common_in_list(adata.obs[match_with][cells_in_cat])
|
|
179
|
+
cats_nums[new_cat] += 1
|
|
180
|
+
vc = vc.cat.rename_categories({cat: f"{new_cat} ({cats_nums[new_cat]})"})
|
|
181
|
+
vdata.obs["leiden"] = vc
|
|
182
|
+
|
|
183
|
+
else: vdata.obs["leiden"].cat.categories = np.arange(
|
|
184
|
+
len(vdata.obs["leiden"].cat.categories))
|
|
185
|
+
adata.obs[f"{vkey}.clusters"] = vdata.obs["leiden"].copy()
|
|
186
|
+
|
|
187
|
+
del vdata
|
|
188
|
+
return None
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
def rank_velocity_genes(
|
|
192
|
+
data,
|
|
193
|
+
vkey = "velocity",
|
|
194
|
+
neighbor_key = 'neighbors',
|
|
195
|
+
highly_variable = 'hvg.vst',
|
|
196
|
+
disp_norm = 'disp.norm',
|
|
197
|
+
likelihood = 'fit.likelihood',
|
|
198
|
+
n_genes = 100,
|
|
199
|
+
groupby = 'velocity.clusters',
|
|
200
|
+
match_with = None,
|
|
201
|
+
resolution = None,
|
|
202
|
+
min_counts = None,
|
|
203
|
+
min_r2 = None,
|
|
204
|
+
min_corr = None,
|
|
205
|
+
min_dispersion = None,
|
|
206
|
+
min_likelihood = None,
|
|
207
|
+
copy = False,
|
|
208
|
+
):
|
|
209
|
+
"""
|
|
210
|
+
Rank genes for velocity characterizing groups.
|
|
211
|
+
|
|
212
|
+
This applies a differential expression test (Welch t-test with overestimated
|
|
213
|
+
variance to be conservative) on velocity expression, to find genes in a cluster that
|
|
214
|
+
show dynamics that is transcriptionally regulated differently compared to all other
|
|
215
|
+
clusters (e.g. induction in that cluster and homeostasis in remaining population).
|
|
216
|
+
If no clusters are given, it priorly computes velocity clusters by applying louvain
|
|
217
|
+
modularity on velocity expression.
|
|
218
|
+
|
|
219
|
+
Parameters
|
|
220
|
+
----------
|
|
221
|
+
data : anndata.AnnData
|
|
222
|
+
Annotated data matrix.
|
|
223
|
+
|
|
224
|
+
vkey: str (default: `'velocity'`)
|
|
225
|
+
Key of velocities computed in `velocity()`
|
|
226
|
+
|
|
227
|
+
n_genes : int, optional (default: 100)
|
|
228
|
+
The number of genes that appear in the returned tables.
|
|
229
|
+
|
|
230
|
+
groupby: str, list or np.ndarray (default: `None`)
|
|
231
|
+
Key of observations grouping to consider.
|
|
232
|
+
|
|
233
|
+
match_with: str or None (default: `None`)
|
|
234
|
+
adata.obs key to separatively rank velocities on.
|
|
235
|
+
|
|
236
|
+
resolution: str or None (default: `None`)
|
|
237
|
+
Resolution for louvain modularity.
|
|
238
|
+
|
|
239
|
+
min_counts: float (default: None)
|
|
240
|
+
Minimum count of genes for consideration.
|
|
241
|
+
|
|
242
|
+
min_r2: float (default: None)
|
|
243
|
+
Minimum r2 value of genes for consideration.
|
|
244
|
+
|
|
245
|
+
min_corr: float (default: None)
|
|
246
|
+
Minimum Spearmans correlation coefficient between spliced and unspliced.
|
|
247
|
+
|
|
248
|
+
min_dispersion: float (default: None)
|
|
249
|
+
Minimum dispersion norm value of genes for consideration.
|
|
250
|
+
|
|
251
|
+
min_likelihood: float between `0` and `1` or `None` (default: `None`)
|
|
252
|
+
Only rank velocity of genes with a likelihood higher than min_likelihood.
|
|
253
|
+
|
|
254
|
+
copy: bool (default: `False`)
|
|
255
|
+
Return a copy instead of writing to data.
|
|
256
|
+
"""
|
|
257
|
+
|
|
258
|
+
adata = data.copy() if copy else data
|
|
259
|
+
|
|
260
|
+
if groupby is None or groupby == "velocity.clusters":
|
|
261
|
+
groupby = f"{vkey}.clusters"
|
|
262
|
+
velocity_clusters(
|
|
263
|
+
adata,
|
|
264
|
+
vkey = vkey,
|
|
265
|
+
neighbor_key = neighbor_key,
|
|
266
|
+
highly_variable = highly_variable,
|
|
267
|
+
disp_norm = disp_norm,
|
|
268
|
+
likelihood = likelihood,
|
|
269
|
+
match_with = match_with,
|
|
270
|
+
resolution = resolution,
|
|
271
|
+
min_likelihood = min_likelihood,
|
|
272
|
+
)
|
|
273
|
+
|
|
274
|
+
info("ranking velocity genes ...")
|
|
275
|
+
|
|
276
|
+
if "spearmans.score" not in adata.var.keys():
|
|
277
|
+
corr = vcorrcoef(
|
|
278
|
+
np.array(adata.layers["ms"]).T,
|
|
279
|
+
np.array(adata.layers["mu"].T),
|
|
280
|
+
mode = "spearmans",
|
|
281
|
+
)
|
|
282
|
+
adata.var["spearmans.score"] = np.clip(corr, 0, None)
|
|
283
|
+
|
|
284
|
+
tmp_filter = ~ np.isnan(adata.layers[vkey].sum(0))
|
|
285
|
+
if f"{vkey}.genes" in adata.var.keys():
|
|
286
|
+
tmp_filter &= np.array(adata.var[f"{vkey}.genes"].values, dtype = bool)
|
|
287
|
+
|
|
288
|
+
if "unspliced" in adata.layers.keys():
|
|
289
|
+
n_counts = (adata.layers["unspliced"] > 0).sum(0)
|
|
290
|
+
n_counts = n_counts.A1 if issparse(adata.layers["unspliced"]) else n_counts
|
|
291
|
+
min_counts = min(50, np.percentile(n_counts, 50)) if min_counts is None else min_counts
|
|
292
|
+
tmp_filter &= np.ravel(n_counts > min_counts)
|
|
293
|
+
|
|
294
|
+
if f"{vkey}.r2" in adata.var.keys():
|
|
295
|
+
r2 = adata.var[f"{vkey}.r2"]
|
|
296
|
+
min_r2 = 0.1 if min_r2 is None else min_r2 # np.percentile(r2[r2 > 0], 50)
|
|
297
|
+
tmp_filter &= r2 > min_r2
|
|
298
|
+
|
|
299
|
+
if "spearmans.score" in adata.var.keys():
|
|
300
|
+
corr = adata.var["spearmans.score"]
|
|
301
|
+
min_corr = (
|
|
302
|
+
0.1 if min_corr is None else min_corr
|
|
303
|
+
) # np.percentile(r2[r2 > 0], 50)
|
|
304
|
+
tmp_filter &= corr > min_corr
|
|
305
|
+
|
|
306
|
+
if disp_norm in adata.var.keys():
|
|
307
|
+
dispersions = adata.var[disp_norm]
|
|
308
|
+
min_dispersion = 0 if min_dispersion is None else min_dispersion
|
|
309
|
+
tmp_filter &= dispersions > min_dispersion
|
|
310
|
+
|
|
311
|
+
if likelihood in adata.var.keys():
|
|
312
|
+
fit_likelihood = adata.var[likelihood]
|
|
313
|
+
min_likelihood = 0.1 if min_likelihood is None else min_likelihood
|
|
314
|
+
tmp_filter &= fit_likelihood > min_likelihood
|
|
315
|
+
|
|
316
|
+
X = adata[:, tmp_filter].layers[vkey]
|
|
317
|
+
groups, groups_masks = select_groups(adata, key=groupby)
|
|
318
|
+
|
|
319
|
+
n_groups = groups_masks.shape[0]
|
|
320
|
+
sizes = groups_masks.sum(1)
|
|
321
|
+
|
|
322
|
+
mean, var = np.zeros((n_groups, X.shape[1])), np.zeros((n_groups, X.shape[1]))
|
|
323
|
+
for i, mask in enumerate(groups_masks):
|
|
324
|
+
mean[i], var[i] = get_mean_var(X[mask])
|
|
325
|
+
|
|
326
|
+
# test each against the union of all other groups
|
|
327
|
+
rankings_gene_names, rankings_gene_scores = [], []
|
|
328
|
+
for i in range(n_groups):
|
|
329
|
+
mask_rest = ~groups_masks[i]
|
|
330
|
+
mean_rest, var_rest = get_mean_var(X[mask_rest])
|
|
331
|
+
size_rest = sizes[i] # else mask_rest.sum() if method == 't-test'
|
|
332
|
+
|
|
333
|
+
scores = (mean[i] - mean_rest) / np.sqrt(
|
|
334
|
+
var[i] / sizes[i] + var_rest / size_rest)
|
|
335
|
+
scores = np.nan_to_num(scores)
|
|
336
|
+
|
|
337
|
+
# equivalent to but much faster than np.argsort(scores)[-10:]
|
|
338
|
+
if n_genes > X.shape[1]: n_genes = X.shape[1]
|
|
339
|
+
idx = np.argpartition(scores, -n_genes)[-n_genes:]
|
|
340
|
+
idx = idx[np.argsort(scores[idx])[::-1]]
|
|
341
|
+
|
|
342
|
+
rankings_gene_names.append(adata[:, tmp_filter].var_names[idx].values)
|
|
343
|
+
rankings_gene_scores.append(scores[idx])
|
|
344
|
+
|
|
345
|
+
rankings_gene_names = np.array([list(n) for n in rankings_gene_names])
|
|
346
|
+
rankings_gene_scores = np.array([list(n) for n in rankings_gene_scores])
|
|
347
|
+
|
|
348
|
+
all_names = rankings_gene_names.T.flatten()
|
|
349
|
+
all_scores = rankings_gene_scores.T.flatten()
|
|
350
|
+
vscore = np.zeros(adata.n_vars, dtype=int)
|
|
351
|
+
for i, name in enumerate(adata.var_names):
|
|
352
|
+
if name in all_names: vscore[i] = all_scores[np.where(name == all_names)[0][0]]
|
|
353
|
+
adata.var["velocity.score"] = vscore
|
|
354
|
+
|
|
355
|
+
key = "rank.velocity.genes"
|
|
356
|
+
if key not in adata.uns.keys(): adata.uns[key] = {}
|
|
357
|
+
|
|
358
|
+
adata.uns[key] = {
|
|
359
|
+
"names": np.rec.fromarrays(
|
|
360
|
+
list(rankings_gene_names), dtype=[(f"{rn}", "U50") for rn in groups]),
|
|
361
|
+
|
|
362
|
+
"scores": np.rec.fromarrays(
|
|
363
|
+
[n.round(2) for n in rankings_gene_scores],
|
|
364
|
+
dtype=[(f"{rn}", "float32") for rn in groups]),
|
|
365
|
+
|
|
366
|
+
"params": {
|
|
367
|
+
"groupby": groupby,
|
|
368
|
+
"reference": "rest",
|
|
369
|
+
"method": "t-test_overestim_var",
|
|
370
|
+
"use_raw": True,
|
|
371
|
+
}
|
|
372
|
+
}
|