exprmat 0.1.13__tar.gz → 0.1.16__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.
Files changed (193) hide show
  1. {exprmat-0.1.13 → exprmat-0.1.16}/PKG-INFO +4 -1
  2. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/__init__.py +1 -1
  3. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/ansi.py +12 -30
  4. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/finders.py +1 -1
  5. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/hsa/mapping-ensembl.pkl +0 -0
  6. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/hsa/mapping-name.pkl +0 -0
  7. exprmat-0.1.16/exprmat/data/mmu/genome.tsv.gz +0 -0
  8. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/mmu/mapping-ensembl.pkl +0 -0
  9. exprmat-0.1.16/exprmat/data/mmu/mapping-name.pkl +0 -0
  10. exprmat-0.1.16/exprmat/data/presets.py +44 -0
  11. exprmat-0.1.16/exprmat/dynamics/__init__.py +90 -0
  12. exprmat-0.1.16/exprmat/dynamics/generank.py +372 -0
  13. exprmat-0.1.16/exprmat/dynamics/linreg.py +144 -0
  14. exprmat-0.1.16/exprmat/dynamics/moments.py +106 -0
  15. exprmat-0.1.16/exprmat/dynamics/optimization.py +202 -0
  16. exprmat-0.1.16/exprmat/dynamics/parallel.py +148 -0
  17. exprmat-0.1.16/exprmat/dynamics/preprocess.py +337 -0
  18. exprmat-0.1.16/exprmat/dynamics/pseudotime.py +459 -0
  19. exprmat-0.1.16/exprmat/dynamics/transition.py +231 -0
  20. exprmat-0.1.16/exprmat/dynamics/utils.py +617 -0
  21. exprmat-0.1.16/exprmat/dynamics/velocity.py +1145 -0
  22. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/plotting/expression.py +69 -0
  23. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/plotting/gse.py +17 -4
  24. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/plotting/summary.py +14 -13
  25. exprmat-0.1.16/exprmat/plotting/utils.py +1 -0
  26. exprmat-0.1.16/exprmat/plotting/velocity.py +595 -0
  27. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/preprocessing/qc.py +6 -0
  28. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/reader/experiment.py +419 -71
  29. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/reader/matcher.py +265 -18
  30. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/reduction/mde.py +39 -2
  31. exprmat-0.1.16/exprmat/reduction/outliers.py +185 -0
  32. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/reduction/plot.py +139 -66
  33. exprmat-0.1.16/exprmat/transfer/__init__.py +0 -0
  34. exprmat-0.1.16/exprmat/transfer/atlas.py +233 -0
  35. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat.egg-info/PKG-INFO +4 -1
  36. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat.egg-info/SOURCES.txt +18 -2
  37. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat.egg-info/requires.txt +3 -0
  38. {exprmat-0.1.13 → exprmat-0.1.16}/setup.py +5 -2
  39. exprmat-0.1.13/exprmat/data/mmu/genome.tsv.gz +0 -0
  40. exprmat-0.1.13/exprmat/data/mmu/mapping-name.pkl +0 -0
  41. exprmat-0.1.13/exprmat/reduction/pumap.py +0 -593
  42. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/clustering/__init__.py +0 -0
  43. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/clustering/leiden.py +0 -0
  44. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/clustering/rogue.py +0 -0
  45. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/clustering/spectral.py +0 -0
  46. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/clustering/utils.py +0 -0
  47. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/cnv/__init__.py +0 -0
  48. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/cnv/cnvscore.py +0 -0
  49. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/cnv/infercnv.py +0 -0
  50. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/configuration.py +0 -0
  51. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/__init__.py +0 -0
  52. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/delim.py +0 -0
  53. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/geneset.py +0 -0
  54. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/gff.py +0 -0
  55. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/hsa/entrez.tsv.gz +0 -0
  56. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/hsa/genesets/all.gmt +0 -0
  57. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/hsa/genesets/bp.gmt +0 -0
  58. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/hsa/genesets/cancer-modules.gmt +0 -0
  59. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/hsa/genesets/cancer-neighborhoods.gmt +0 -0
  60. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/hsa/genesets/cancer.gmt +0 -0
  61. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/hsa/genesets/cc.gmt +0 -0
  62. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/hsa/genesets/chemical-perturb.gmt +0 -0
  63. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/hsa/genesets/hallmark.gmt +0 -0
  64. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/hsa/genesets/human-phenotype-ontology.gmt +0 -0
  65. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/hsa/genesets/immune-perturb.gmt +0 -0
  66. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/hsa/genesets/kegg.gmt +0 -0
  67. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/hsa/genesets/mf.gmt +0 -0
  68. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/hsa/genesets/microrna.gmt +0 -0
  69. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/hsa/genesets/oncogenic.gmt +0 -0
  70. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/hsa/genesets/pathways.gmt +0 -0
  71. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/hsa/genesets/positional.gmt +0 -0
  72. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/hsa/genesets/single-cell.gmt +0 -0
  73. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/hsa/genesets/transcript-factors.gmt +0 -0
  74. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/hsa/genesets/vaccine.gmt +0 -0
  75. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/hsa/genome.tsv.gz +0 -0
  76. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/hsa/lr/baccin2019 +0 -0
  77. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/hsa/lr/cellcall +0 -0
  78. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/hsa/lr/cellchatdb +0 -0
  79. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/hsa/lr/cellinker +0 -0
  80. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/hsa/lr/cellphonedb +0 -0
  81. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/hsa/lr/celltalkdb +0 -0
  82. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/hsa/lr/connectomedb2020 +0 -0
  83. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/hsa/lr/consensus +0 -0
  84. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/hsa/lr/embrace +0 -0
  85. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/hsa/lr/guide2pharma +0 -0
  86. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/hsa/lr/hpmr +0 -0
  87. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/hsa/lr/icellnet +0 -0
  88. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/hsa/lr/italk +0 -0
  89. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/hsa/lr/kirouac2010 +0 -0
  90. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/hsa/lr/lrdb +0 -0
  91. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/hsa/lr/ramilowski2015 +0 -0
  92. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/hsa/orthologs/aca.tsv.gz +0 -0
  93. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/hsa/orthologs/bta.tsv.gz +0 -0
  94. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/hsa/orthologs/cel.tsv.gz +0 -0
  95. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/hsa/orthologs/clu.tsv.gz +0 -0
  96. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/hsa/orthologs/dme.tsv.gz +0 -0
  97. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/hsa/orthologs/dre.tsv.gz +0 -0
  98. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/hsa/orthologs/eca.tsv.gz +0 -0
  99. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/hsa/orthologs/fca.tsv.gz +0 -0
  100. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/hsa/orthologs/gga.tsv.gz +0 -0
  101. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/hsa/orthologs/mdo.tsv.gz +0 -0
  102. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/hsa/orthologs/mmu.tsv.gz +0 -0
  103. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/hsa/orthologs/mmul.gz +0 -0
  104. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/hsa/orthologs/oan.tsv.gz +0 -0
  105. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/hsa/orthologs/ptr.tsv.gz +0 -0
  106. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/hsa/orthologs/rno.tsv.gz +0 -0
  107. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/hsa/orthologs/sce.tsv.gz +0 -0
  108. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/hsa/orthologs/spo.tsv.gz +0 -0
  109. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/hsa/orthologs/ssc.tsv.gz +0 -0
  110. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/hsa/orthologs/xla.tsv.gz +0 -0
  111. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/hsa/taxa +0 -0
  112. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/lr.py +0 -0
  113. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/mmu/entrez.tsv.gz +0 -0
  114. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/mmu/genesets/all.gmt +0 -0
  115. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/mmu/genesets/azimuth.gmt +0 -0
  116. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/mmu/genesets/biocarta.gmt +0 -0
  117. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/mmu/genesets/bp.gmt +0 -0
  118. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/mmu/genesets/cc.gmt +0 -0
  119. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/mmu/genesets/chemical-perturb.gmt +0 -0
  120. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/mmu/genesets/hallmark.gmt +0 -0
  121. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/mmu/genesets/kegg.gmt +0 -0
  122. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/mmu/genesets/m2.gmt +0 -0
  123. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/mmu/genesets/markers.gmt +0 -0
  124. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/mmu/genesets/mf.gmt +0 -0
  125. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/mmu/genesets/microrna.gmt +0 -0
  126. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/mmu/genesets/mpt.gmt +0 -0
  127. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/mmu/genesets/positional.gmt +0 -0
  128. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/mmu/genesets/reactome.gmt +0 -0
  129. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/mmu/genesets/transcript-factors.gmt +0 -0
  130. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/mmu/genesets/wikipathway.gmt +0 -0
  131. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/mmu/lr/consensus +0 -0
  132. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/mmu/taxa +0 -0
  133. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/private.py +0 -0
  134. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/data/ranges.py +0 -0
  135. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/descriptive/__init__.py +0 -0
  136. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/descriptive/aggregate.py +0 -0
  137. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/descriptive/de.py +0 -0
  138. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/descriptive/gse.py +0 -0
  139. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/descriptive/kde.py +0 -0
  140. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/descriptive/summary.py +0 -0
  141. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/descriptive/tcr.py +0 -0
  142. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/lr/__init__.py +0 -0
  143. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/lr/aggregate.py +0 -0
  144. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/lr/method.py +0 -0
  145. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/lr/methods/__init__.py +0 -0
  146. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/lr/methods/cellchat.py +0 -0
  147. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/lr/methods/cellphonedb.py +0 -0
  148. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/lr/methods/connectome.py +0 -0
  149. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/lr/methods/geomean.py +0 -0
  150. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/lr/methods/logfc.py +0 -0
  151. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/lr/methods/natmi.py +0 -0
  152. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/lr/methods/rank_aggregate.py +0 -0
  153. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/lr/methods/scseqcomm.py +0 -0
  154. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/lr/methods/singlecellsignalr.py +0 -0
  155. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/lr/pipeline.py +0 -0
  156. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/lr/preprocess.py +0 -0
  157. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/lr/resources.py +0 -0
  158. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/lr/utils.py +0 -0
  159. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/plotting/__init__.py +0 -0
  160. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/plotting/cnv.py +0 -0
  161. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/plotting/de.py +0 -0
  162. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/plotting/lr.py +0 -0
  163. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/plotting/palettes.py +0 -0
  164. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/plotting/sankey.py +0 -0
  165. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/preprocessing/__init__.py +0 -0
  166. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/preprocessing/doublets/__init__.py +0 -0
  167. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/preprocessing/doublets/composite.py +0 -0
  168. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/preprocessing/doublets/scrublet.py +0 -0
  169. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/preprocessing/filter.py +0 -0
  170. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/preprocessing/integrate.py +0 -0
  171. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/preprocessing/linear.py +0 -0
  172. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/preprocessing/normal.py +0 -0
  173. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/preprocessing/plot.py +0 -0
  174. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/preprocessing/sctransform/__init__.py +0 -0
  175. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/preprocessing/sctransform/estimate.py +0 -0
  176. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/preprocessing/sctransform/ksmooth.py +0 -0
  177. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/preprocessing/sctransform/residual.py +0 -0
  178. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/preprocessing/sctransform/transform.py +0 -0
  179. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/preprocessing/sparse.py +0 -0
  180. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/preprocessing/uniform.py +0 -0
  181. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/reader/__init__.py +0 -0
  182. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/reader/metadata.py +0 -0
  183. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/reduction/__init__.py +0 -0
  184. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/reduction/forceatlas.py +0 -0
  185. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/reduction/nn.py +0 -0
  186. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/reduction/pca.py +0 -0
  187. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/reduction/tsne.py +0 -0
  188. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/reduction/umap.py +0 -0
  189. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat/utils.py +0 -0
  190. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat.egg-info/dependency_links.txt +0 -0
  191. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat.egg-info/not-zip-safe +0 -0
  192. {exprmat-0.1.13 → exprmat-0.1.16}/exprmat.egg-info/top_level.txt +0 -0
  193. {exprmat-0.1.13 → exprmat-0.1.16}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: exprmat
3
- Version: 0.1.13
3
+ Version: 0.1.16
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
@@ -4,4 +4,4 @@ import anndata as ad
4
4
 
5
5
  mu.set_options(pull_on_update = False)
6
6
 
7
- def version(): return 'exprmat 0.1.13-1 [dev]'
7
+ def version(): return 'exprmat 0.1.16-1 [dev]'
@@ -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
- # reset ansi controls ---------------------------------------------------------
44
-
34
+
45
35
  def ansi_reset() -> None:
46
36
  print('\033[0m', end = '')
47
37
 
48
- # backgrounds -----------------------------------------------------------------
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
- # prompt messages -------------------------------------------------------------
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
- raise Exception()
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']
@@ -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,90 @@
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
+
52
+
53
+ def clean_velocity_results(adata, vkey = 'velocity'):
54
+
55
+ for x in list(adata.obs.keys()):
56
+ if x in [
57
+ 'root.cells',
58
+ 'endpoints',
59
+ 'n.umi.spliced',
60
+ 'n.umi.unspliced',
61
+ 'velocity.pseudotime'
62
+ ]: del adata.obs[x]
63
+ elif x.startswith(f'{vkey}.'): del adata.obs[x]
64
+
65
+ for x in list(adata.var.keys()):
66
+ if x.startswith(f'{vkey}.'): del adata.var[x]
67
+ elif x in ['gene.count.corr']: del adata.var[x]
68
+
69
+ for x in list(adata.layers.keys()):
70
+ if x in ['ms', 'mu', vkey, f'variance.{vkey}']: del adata.layers[x]
71
+ elif ('spliced.counts' in adata.layers.keys()) and x == 'spliced':
72
+ del adata.layers['spliced']
73
+ adata.layers['spliced'] = adata.layers['spliced.counts'].copy()
74
+ del adata.layers['spliced.counts']
75
+ elif ('unspliced.counts' in adata.layers.keys()) and x == 'unspliced':
76
+ del adata.layers['unspliced']
77
+ adata.layers['unspliced'] = adata.layers['unspliced.counts'].copy()
78
+ del adata.layers['unspliced.counts']
79
+
80
+ for x in list(adata.obsm.keys()):
81
+ if x.startswith(f'{vkey}.'): del adata.obsm[x]
82
+ elif x.startswith('vdiff.'): del adata.obsm[x]
83
+ elif x == 'vdiff': del adata.obsm[x]
84
+
85
+ for x in list(adata.uns.keys()):
86
+ if x in [
87
+ f'{vkey}.graph',
88
+ f'{vkey}.graph.neg',
89
+ f'{vkey}.params'
90
+ ]: del adata.uns[x]
@@ -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
+ }