exprmat 0.1.47__tar.gz → 0.1.48__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.47 → exprmat-0.1.48}/PKG-INFO +1 -1
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/__init__.py +22 -7
- exprmat-0.1.48/exprmat/clustering/gating.py +64 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/clustering/nmf.py +0 -1
- exprmat-0.1.48/exprmat/clustering/sc3.py +438 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/clustering/seriation.py +5 -4
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/data/lr.py +7 -39
- exprmat-0.1.48/exprmat/data/orthologs.py +107 -0
- exprmat-0.1.48/exprmat/deconv/deconv.py +415 -0
- exprmat-0.1.48/exprmat/deconv/simulation.py +103 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/metacell/__init__.py +0 -3
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/plotting/cnmf.py +6 -4
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/plotting/expression.py +8 -3
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/plotting/lr.py +23 -5
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/plotting/utils.py +15 -6
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/preprocessing/__init__.py +9 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/preprocessing/plot.py +3 -2
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/preprocessing/qc.py +11 -8
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/reader/experiment.py +161 -13
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/reader/matcher.py +123 -1
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/reader/static.py +230 -29
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/reduction/plot.py +16 -4
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/reduction/scvi.py +4 -1
- exprmat-0.1.48/exprmat/trajectory/cytotrace.py +617 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/transfer/atlas.py +155 -78
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/utils.py +1 -0
- exprmat-0.1.48/license +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/pyproject.toml +1 -1
- {exprmat-0.1.47 → exprmat-0.1.48}/Cargo.lock +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/Cargo.toml +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/ansi.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/clustering/__init__.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/clustering/cnmf.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/clustering/dbscan.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/clustering/kmeans.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/clustering/leiden.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/clustering/rogue.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/clustering/spectral.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/clustering/utils.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/cnv/__init__.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/cnv/cnvscore.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/cnv/infercnv.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/configuration.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/data/__init__.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/data/cistarget.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/data/cre.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/data/finders.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/data/geneset.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/data/io.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/data/presets.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/data/signature.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/data/tf.py +0 -0
- {exprmat-0.1.47/exprmat/descriptive → exprmat-0.1.48/exprmat/deconv}/__init__.py +0 -0
- {exprmat-0.1.47/exprmat/image → exprmat-0.1.48/exprmat/descriptive}/__init__.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/descriptive/aggregate.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/descriptive/atac.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/descriptive/aucell.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/descriptive/de.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/descriptive/gse.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/descriptive/kde.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/descriptive/recovery.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/descriptive/summary.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/descriptive/tcr.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/deseq/dataset.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/deseq/gridsearch.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/deseq/inference.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/deseq/preprocessing.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/deseq/stats.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/deseq/utils.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/dynamics/__init__.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/dynamics/generank.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/dynamics/linreg.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/dynamics/moments.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/dynamics/optimization.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/dynamics/parallel.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/dynamics/preprocess.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/dynamics/pseudotime.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/dynamics/transition.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/dynamics/utils.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/dynamics/velocity.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/grn/__init__.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/grn/infergrn.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/grn/modules.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/grn/prune.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/grn/regressors.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/grn/utils.py +0 -0
- {exprmat-0.1.47/exprmat/lr/methods → exprmat-0.1.48/exprmat/image}/__init__.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/image/align.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/lr/__init__.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/lr/aggregate.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/lr/method.py +0 -0
- {exprmat-0.1.47/exprmat/peaks → exprmat-0.1.48/exprmat/lr/methods}/__init__.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/lr/methods/cellchat.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/lr/methods/cellphonedb.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/lr/methods/connectome.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/lr/methods/geomean.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/lr/methods/logfc.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/lr/methods/natmi.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/lr/methods/rank_aggregate.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/lr/methods/scseqcomm.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/lr/methods/singlecellsignalr.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/lr/pipeline.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/lr/preprocess.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/lr/resources.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/lr/utils.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/metacell/engine.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/metacell/model.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/metacell/utils.py +0 -0
- {exprmat-0.1.47/exprmat/peaks/idr → exprmat-0.1.48/exprmat/peaks}/__init__.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/peaks/callpeak.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/peaks/common.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/peaks/coverage.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/peaks/footprint.py +0 -0
- {exprmat-0.1.47/exprmat/preprocessing/doublets → exprmat-0.1.48/exprmat/peaks/idr}/__init__.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/peaks/idr/constants.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/peaks/idr/idr.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/peaks/idr/invcdf.pyx +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/peaks/idr/optimization.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/peaks/idr/utils.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/peaks/linkage.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/peaks/motif.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/peaks/sequence.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/plotting/__init__.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/plotting/atac.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/plotting/cnv.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/plotting/data/A.pk +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/plotting/data/B.pk +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/plotting/data/C.pk +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/plotting/data/D.pk +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/plotting/data/E.pk +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/plotting/data/F.pk +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/plotting/data/G.pk +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/plotting/data/H.pk +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/plotting/data/I.pk +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/plotting/data/J.pk +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/plotting/data/K.pk +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/plotting/data/L.pk +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/plotting/data/M.pk +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/plotting/data/N.pk +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/plotting/data/O.pk +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/plotting/data/P.pk +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/plotting/data/Q.pk +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/plotting/data/R.pk +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/plotting/data/S.pk +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/plotting/data/T.pk +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/plotting/data/U.pk +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/plotting/data/V.pk +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/plotting/data/W.pk +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/plotting/data/X.pk +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/plotting/data/Y.pk +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/plotting/data/Z.pk +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/plotting/de.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/plotting/gse.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/plotting/milestone.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/plotting/palettes.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/plotting/sankey.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/plotting/sequence.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/plotting/summary.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/plotting/track.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/plotting/trajectory.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/plotting/velocity.py +0 -0
- {exprmat-0.1.47/exprmat/preprocessing/impute → exprmat-0.1.48/exprmat/preprocessing/doublets}/__init__.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/preprocessing/doublets/composite.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/preprocessing/doublets/scrublet.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/preprocessing/emptydrops.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/preprocessing/filter.py +0 -0
- {exprmat-0.1.47/exprmat/preprocessing/sctransform → exprmat-0.1.48/exprmat/preprocessing/impute}/__init__.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/preprocessing/impute/magic.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/preprocessing/integrate.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/preprocessing/linear.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/preprocessing/normal.py +0 -0
- {exprmat-0.1.47/exprmat/reader → exprmat-0.1.48/exprmat/preprocessing/sctransform}/__init__.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/preprocessing/sctransform/estimate.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/preprocessing/sctransform/ksmooth.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/preprocessing/sctransform/residual.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/preprocessing/sctransform/transform.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/preprocessing/sparse.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/preprocessing/uniform.py +0 -0
- {exprmat-0.1.47/exprmat/trajectory → exprmat-0.1.48/exprmat/reader}/__init__.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/reader/conversions.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/reader/metadata.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/reader/spatial.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/reader/updater.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/reduction/__init__.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/reduction/diffmap.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/reduction/forceatlas.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/reduction/mde.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/reduction/nn.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/reduction/outliers.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/reduction/pca.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/reduction/spectral.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/reduction/tsne.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/reduction/umap.py +0 -0
- {exprmat-0.1.47/exprmat/transfer → exprmat-0.1.48/exprmat/trajectory}/__init__.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/trajectory/elpi.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/trajectory/pcurve.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/trajectory/pseudotime.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/trajectory/root.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/exprmat/trajectory/trace.py +0 -0
- /exprmat-0.1.47/license → /exprmat-0.1.48/exprmat/transfer/__init__.py +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/readme.md +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/snapatac2/Cargo.toml +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/snapatac2/license +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/snapatac2/readme +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/snapatac2/src/call_peaks.rs +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/snapatac2/src/embedding.rs +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/snapatac2/src/export.rs +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/snapatac2/src/knn.rs +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/snapatac2/src/lib.rs +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/snapatac2/src/motif.rs +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/snapatac2/src/network.rs +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/snapatac2/src/preprocessing.rs +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/snapatac2/src/utils/anndata.rs +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/snapatac2/src/utils.rs +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/snapatac2-core/Cargo.toml +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/snapatac2-core/src/embedding.rs +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/snapatac2-core/src/export.rs +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/snapatac2-core/src/feature_count/counter.rs +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/snapatac2-core/src/feature_count/data_iter.rs +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/snapatac2-core/src/feature_count/matrix.rs +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/snapatac2-core/src/feature_count/mod.rs +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/snapatac2-core/src/genome.rs +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/snapatac2-core/src/lib.rs +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/snapatac2-core/src/motif.rs +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/snapatac2-core/src/network.rs +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/snapatac2-core/src/preprocessing/bam/flagstat.rs +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/snapatac2-core/src/preprocessing/bam/header.rs +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/snapatac2-core/src/preprocessing/bam/mark_duplicates.rs +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/snapatac2-core/src/preprocessing/bam.rs +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/snapatac2-core/src/preprocessing/import.rs +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/snapatac2-core/src/preprocessing/mod.rs +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/snapatac2-core/src/preprocessing/qc.rs +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/snapatac2-core/src/utils/knn.rs +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/snapatac2-core/src/utils/mod.rs +0 -0
- {exprmat-0.1.47 → exprmat-0.1.48}/snapatac2-core/src/utils/similarity.rs +0 -0
|
@@ -14,10 +14,13 @@ os.environ['OPENBLAS_NUM_THREADS'] = '1'
|
|
|
14
14
|
os.environ['GOTO_NUM_THREADS'] = '1'
|
|
15
15
|
os.environ['OMP_NUM_THREADS'] = '1'
|
|
16
16
|
|
|
17
|
+
# public expose references
|
|
17
18
|
import mudata as mu
|
|
18
19
|
import anndata as ad
|
|
19
20
|
import scanpy as sc
|
|
20
21
|
import pandas as pd
|
|
22
|
+
import numpy as np
|
|
23
|
+
|
|
21
24
|
import pathlib
|
|
22
25
|
from PIL import Image
|
|
23
26
|
|
|
@@ -109,7 +112,7 @@ basepath = config['data']
|
|
|
109
112
|
|
|
110
113
|
# core method exports
|
|
111
114
|
from exprmat.utils import setup_styles, savefig
|
|
112
|
-
from exprmat.ansi import
|
|
115
|
+
from exprmat.ansi import pprog, pproga, info, error, warning
|
|
113
116
|
from exprmat.reader.experiment import experiment, load_experiment
|
|
114
117
|
from exprmat.reader.metadata import metadata, load_metadata
|
|
115
118
|
import exprmat.reader.static as st
|
|
@@ -192,24 +195,36 @@ def memory():
|
|
|
192
195
|
setwd = os.chdir
|
|
193
196
|
getwd = os.getcwd
|
|
194
197
|
|
|
198
|
+
import tqdm
|
|
199
|
+
# https://github.com/tqdm/tqdm/issues/457
|
|
200
|
+
tqdm.tqdm(disable = True, total = 0)
|
|
201
|
+
|
|
195
202
|
|
|
196
203
|
__all__ = [
|
|
197
|
-
|
|
204
|
+
# exposed external namespace
|
|
205
|
+
'np', 'mu', 'ad', 'sc', 'pd',
|
|
206
|
+
|
|
207
|
+
# exposed internal namespace
|
|
208
|
+
'st',
|
|
209
|
+
|
|
210
|
+
# expose classes
|
|
198
211
|
'experiment',
|
|
199
212
|
'metadata',
|
|
213
|
+
'configuration'
|
|
214
|
+
|
|
215
|
+
# top-level methods
|
|
200
216
|
'load_experiment',
|
|
201
217
|
'load_metadata',
|
|
202
218
|
'version',
|
|
203
|
-
'
|
|
219
|
+
'version_db'
|
|
204
220
|
'cuda',
|
|
221
|
+
'memory',
|
|
205
222
|
'setwd',
|
|
206
223
|
'getwd',
|
|
207
|
-
'error',
|
|
208
|
-
'warning',
|
|
209
|
-
'info',
|
|
210
224
|
'pprog',
|
|
211
225
|
'pproga',
|
|
212
226
|
'savefig',
|
|
213
227
|
|
|
214
|
-
|
|
228
|
+
# constants
|
|
229
|
+
'SPECIFICATION'
|
|
215
230
|
]
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
|
|
2
|
+
import numpy as np
|
|
3
|
+
from shapely import Point, Polygon
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def polygon_gate(
|
|
7
|
+
adata, gene_x, gene_y,
|
|
8
|
+
layer = 'X',
|
|
9
|
+
|
|
10
|
+
remove_zero_expression = False,
|
|
11
|
+
scale = 'asis', arcsinh_divider = None,
|
|
12
|
+
|
|
13
|
+
polygon = [(0, 0), (1, 0), (1, 1), (0, 1)],
|
|
14
|
+
key_added = 'gate'
|
|
15
|
+
):
|
|
16
|
+
|
|
17
|
+
import pandas as pd
|
|
18
|
+
import seaborn as sb
|
|
19
|
+
from scipy.sparse import issparse
|
|
20
|
+
from exprmat.plotting import palettes
|
|
21
|
+
|
|
22
|
+
gx = None
|
|
23
|
+
gy = None
|
|
24
|
+
|
|
25
|
+
# assign gene X.
|
|
26
|
+
from exprmat.utils import find_variable as find_var
|
|
27
|
+
gx = find_var(adata, gene_name = gene_x, layer = layer)
|
|
28
|
+
gy = find_var(adata, gene_name = gene_y, layer = layer)
|
|
29
|
+
|
|
30
|
+
df = pd.DataFrame({
|
|
31
|
+
'id': adata.obs_names.tolist(),
|
|
32
|
+
'x': gx,
|
|
33
|
+
'y': gy
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
if remove_zero_expression:
|
|
37
|
+
df = df.loc[(df['x'] > 0) & (df['y'] > 0), :].copy()
|
|
38
|
+
|
|
39
|
+
if scale == 'asis': pass
|
|
40
|
+
elif scale == 'log':
|
|
41
|
+
df['x'] = np.log1p(df['x'])
|
|
42
|
+
df['y'] = np.log1p(df['y'])
|
|
43
|
+
elif scale == 'expm1':
|
|
44
|
+
df['x'] = np.expm1(df['x'])
|
|
45
|
+
df['y'] = np.expm1(df['y'])
|
|
46
|
+
elif scale == 'arcsinh':
|
|
47
|
+
lx = np.expm1(df['x']).loc[df['x'] > 0]
|
|
48
|
+
ly = np.expm1(df['y']).loc[df['x'] > 0]
|
|
49
|
+
df['x'] = np.arcsinh(np.expm1(df['x']) / (
|
|
50
|
+
arcsinh_divider if arcsinh_divider is not None
|
|
51
|
+
else (np.median(lx) / 20)))
|
|
52
|
+
df['y'] = np.arcsinh(np.expm1(df['y']) / (
|
|
53
|
+
arcsinh_divider if arcsinh_divider is not None
|
|
54
|
+
else (np.median(ly) / 20)))
|
|
55
|
+
|
|
56
|
+
poly = Polygon(polygon)
|
|
57
|
+
df['gate'] = [
|
|
58
|
+
poly.contains(Point(x, y))
|
|
59
|
+
for x, y in zip(df['x'], df['y'])
|
|
60
|
+
]
|
|
61
|
+
|
|
62
|
+
df.index = df['id'].tolist()
|
|
63
|
+
adata.obs[key_added] = False
|
|
64
|
+
adata.obs.loc[df.index, key_added] = df['gate']
|
|
@@ -0,0 +1,438 @@
|
|
|
1
|
+
|
|
2
|
+
# special objects for the trials dictionary
|
|
3
|
+
from collections import namedtuple
|
|
4
|
+
rk = namedtuple('trial_params', 'd, i')
|
|
5
|
+
import pandas
|
|
6
|
+
from sklearn.utils import check_random_state
|
|
7
|
+
|
|
8
|
+
from exprmat import info, warning, error
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
# value
|
|
12
|
+
def rv(**kwargs):
|
|
13
|
+
"""
|
|
14
|
+
Basically a nice wrapper around kwargs to avoid having to type out dictionary syntax.
|
|
15
|
+
Returns dictionary object.
|
|
16
|
+
"""
|
|
17
|
+
return kwargs
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def check_integer_list(
|
|
21
|
+
num_list, min_val = None, max_val = None,
|
|
22
|
+
var_name = "variable", return_as_list = True):
|
|
23
|
+
|
|
24
|
+
# formats into an iterable
|
|
25
|
+
_check_integer_boolean = isinstance(num_list, int)
|
|
26
|
+
|
|
27
|
+
if _check_integer_boolean:
|
|
28
|
+
num_list = [num_list]
|
|
29
|
+
elif isinstance(num_list, range):
|
|
30
|
+
if len(num_list) == 0: error(f"{var_name} specified range has length 0.")
|
|
31
|
+
else: pass
|
|
32
|
+
elif isinstance(num_list, list):
|
|
33
|
+
if len(num_list) == 0: error(f"{var_name} specified list has length 0.")
|
|
34
|
+
else:
|
|
35
|
+
for num in num_list:
|
|
36
|
+
if not isinstance(num, int):
|
|
37
|
+
error(f"{var_name} values must be integers.")
|
|
38
|
+
else: pass
|
|
39
|
+
else: error(f"{var_name} must be integer, or a non-empty list/range.")
|
|
40
|
+
|
|
41
|
+
# check that each value in the iterable satisfies the limits
|
|
42
|
+
for num in num_list:
|
|
43
|
+
if min_val is not None:
|
|
44
|
+
if num < min_val: error(f"{var_name} must be greater than {min_val}.")
|
|
45
|
+
if max_val is not None:
|
|
46
|
+
if num > max_val: error(f"{var_name} must be less than {max_val}.")
|
|
47
|
+
|
|
48
|
+
# the formated integer can be returned in the original format if specified
|
|
49
|
+
if _check_integer_boolean and return_as_list == False:
|
|
50
|
+
num_list = num_list[0]
|
|
51
|
+
|
|
52
|
+
return num_list
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def check_integer(num, min_val = None, max_val = None, var_name = "variable"):
|
|
56
|
+
|
|
57
|
+
# check that it is an integer
|
|
58
|
+
if not isinstance(num, int):
|
|
59
|
+
error(f"{var_name}: must be an integer.")
|
|
60
|
+
|
|
61
|
+
# check that the integer value satisfies the limits
|
|
62
|
+
if min_val is not None:
|
|
63
|
+
if num < min_val: error(f"{var_name} must be greater than {min_val}.")
|
|
64
|
+
if max_val is not None:
|
|
65
|
+
if num > max_val: error(f"{var_name} must be less than {max_val}.")
|
|
66
|
+
|
|
67
|
+
return num
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def check_dict(dict_object, true_n_clusters, true_n_cells):
|
|
71
|
+
|
|
72
|
+
# check n_clusters and n_cells are integers
|
|
73
|
+
true_n_clusters = check_integer(true_n_clusters)
|
|
74
|
+
true_n_cells = check_integer(true_n_cells)
|
|
75
|
+
|
|
76
|
+
# check the number of cells
|
|
77
|
+
n_cells_list = [len(x['labels']) for x in dict_object.values()]
|
|
78
|
+
assert n_cells_list.count(true_n_cells) == len(n_cells_list), "number of cells is not consistent between trials"
|
|
79
|
+
n_cells = true_n_cells
|
|
80
|
+
|
|
81
|
+
# check the number of clusters
|
|
82
|
+
n_clusters_list = [x['facility'].shape[0] for x in dict_object.values()]
|
|
83
|
+
assert n_clusters_list.count(true_n_clusters) == len(n_clusters_list), "number of clusters not consistent between trials"
|
|
84
|
+
n_clusters = true_n_clusters
|
|
85
|
+
|
|
86
|
+
return dict_object
|
|
87
|
+
|
|
88
|
+
# check the number of cells
|
|
89
|
+
# n_cells_list = [len(x['labels']) for x in dict_object.values()]
|
|
90
|
+
# assert n_cells_list.count(true_n_cells) == len(n_cells_list), "number of cells not consistent"
|
|
91
|
+
# n_cells = true_n_cells
|
|
92
|
+
|
|
93
|
+
# # check the number of clusters
|
|
94
|
+
# # there is an edge case for this, which is if the kth cluster is not assigned any cells
|
|
95
|
+
# # will fix if error occurs, otherwise can just count that at least 75% of runs is correct?
|
|
96
|
+
# n_clusters_list = [np.max(x['labels']) + 1 for x in dict_object.values()]
|
|
97
|
+
# assert n_clusters_list.count(true_n_clusters) == len(n_clusters_list), "number of cells not consistent"
|
|
98
|
+
# n_clusters = true_n_clusters
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def run_trials_minibatch_kmeans(data, n_clusters, d_range, n_runs, batch_size, random_state):
|
|
102
|
+
|
|
103
|
+
import itertools
|
|
104
|
+
from sklearn.cluster import MiniBatchKMeans
|
|
105
|
+
|
|
106
|
+
# check that consensus matrix has no NaN, infinity values
|
|
107
|
+
from sklearn.utils import check_array
|
|
108
|
+
data = check_array(data)
|
|
109
|
+
|
|
110
|
+
# check n_clusters
|
|
111
|
+
n_clusters = check_integer(
|
|
112
|
+
n_clusters,
|
|
113
|
+
min_val = 2,
|
|
114
|
+
var_name = 'n_clusters'
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
# check d_range
|
|
118
|
+
d_range = check_integer_list(
|
|
119
|
+
d_range,
|
|
120
|
+
min_val = 2,
|
|
121
|
+
max_val = data.shape[1],
|
|
122
|
+
var_name = 'd_range'
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
# check n_runs
|
|
126
|
+
n_runs = check_integer(n_runs, min_val=1, var_name="n_runs")
|
|
127
|
+
|
|
128
|
+
# check batch_size
|
|
129
|
+
batch_size = check_integer(
|
|
130
|
+
batch_size,
|
|
131
|
+
min_val = 10,
|
|
132
|
+
max_val = data.shape[0],
|
|
133
|
+
var_name = 'batch_size'
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
# check random state
|
|
137
|
+
from sklearn.utils import check_random_state
|
|
138
|
+
random_state = check_random_state(random_state)
|
|
139
|
+
|
|
140
|
+
trials_dict = {}
|
|
141
|
+
for d, i in itertools.product(d_range, range(1, n_runs + 1)):
|
|
142
|
+
kmeans = MiniBatchKMeans(
|
|
143
|
+
n_clusters = n_clusters,
|
|
144
|
+
batch_size = batch_size,
|
|
145
|
+
random_state = random_state
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
# cluster the points
|
|
149
|
+
kmeans.fit(data[:, :d])
|
|
150
|
+
|
|
151
|
+
# add results into dictionary
|
|
152
|
+
trials_dict[(d, i)] = rv(
|
|
153
|
+
facility = kmeans.cluster_centers_,
|
|
154
|
+
labels = kmeans.labels_,
|
|
155
|
+
inertia = kmeans.inertia_
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
return trials_dict
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def combine_facilities(dict_object, K, n_facility, batch_size, random_state):
|
|
162
|
+
|
|
163
|
+
from sklearn.cluster import MiniBatchKMeans
|
|
164
|
+
import numpy as np
|
|
165
|
+
|
|
166
|
+
# check that the dictionary object is formatted correctly
|
|
167
|
+
assert isinstance(dict_object, dict)
|
|
168
|
+
for key, value in dict_object.items():
|
|
169
|
+
assert isinstance(value, dict)
|
|
170
|
+
assert value['facility'] is not None
|
|
171
|
+
assert value['labels'] is not None
|
|
172
|
+
|
|
173
|
+
# check arguments are formated as integers (limits not trivial to do)
|
|
174
|
+
K = check_integer(K, var_name = 'K')
|
|
175
|
+
n_facility = check_integer(n_facility, var_name = 'n_facility')
|
|
176
|
+
batch_size = check_integer(batch_size, var_name = 'batch_size')
|
|
177
|
+
|
|
178
|
+
# check random state
|
|
179
|
+
from sklearn.utils import check_random_state
|
|
180
|
+
random_state = check_random_state(random_state)
|
|
181
|
+
|
|
182
|
+
dict_object_combined = {}
|
|
183
|
+
|
|
184
|
+
# combine the facilities from different trials
|
|
185
|
+
for key, value in dict_object.items():
|
|
186
|
+
facilities = value['facility']
|
|
187
|
+
labels = value['labels']
|
|
188
|
+
|
|
189
|
+
# count the number of cells assigned to each facility
|
|
190
|
+
weights = list(map(
|
|
191
|
+
lambda cluster_no: np.count_nonzero(labels == cluster_no),
|
|
192
|
+
range(0, n_facility)
|
|
193
|
+
))
|
|
194
|
+
|
|
195
|
+
# cluster the facility using weighted k means
|
|
196
|
+
kmeans = MiniBatchKMeans(
|
|
197
|
+
n_clusters = K,
|
|
198
|
+
batch_size = batch_size,
|
|
199
|
+
random_state = random_state
|
|
200
|
+
)
|
|
201
|
+
kmeans.fit(facilities, sample_weight = weights)
|
|
202
|
+
|
|
203
|
+
# write result
|
|
204
|
+
dict_object_combined[key] = rv(
|
|
205
|
+
facility = kmeans.cluster_centers_,
|
|
206
|
+
labels = kmeans.labels_[labels],
|
|
207
|
+
inertia = kmeans.inertia_
|
|
208
|
+
)
|
|
209
|
+
|
|
210
|
+
return dict_object_combined
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
def convert_dict_into_binary_matrix(dict_object, true_n_clusters, true_n_cells):
|
|
215
|
+
|
|
216
|
+
import numpy as np
|
|
217
|
+
|
|
218
|
+
n_clusters, n_cells = true_n_clusters, true_n_cells
|
|
219
|
+
|
|
220
|
+
# check dict_object has correct number of clusters and cells for every run
|
|
221
|
+
dict_object = check_dict(dict_object, true_n_clusters, true_n_cells)
|
|
222
|
+
|
|
223
|
+
# initialise empty B array with the correct shape
|
|
224
|
+
B = np.zeros((n_cells, 0), dtype=int)
|
|
225
|
+
|
|
226
|
+
# for each run, we create the block to be appended to B
|
|
227
|
+
for i, value in enumerate(dict_object.values()):
|
|
228
|
+
cell_labels = value['labels']
|
|
229
|
+
|
|
230
|
+
# create a total of 'n_clusters' columns for this iteration
|
|
231
|
+
b = np.zeros((n_cells, n_clusters), dtype=int)
|
|
232
|
+
|
|
233
|
+
# annotate the correct columns for each row/cell
|
|
234
|
+
b[range(0, n_cells), cell_labels] = 1
|
|
235
|
+
|
|
236
|
+
# this checks that every cell only has one cluster assignment
|
|
237
|
+
assert np.all(np.sum(b, axis=1) == 1), "some cells have multiple cluster assignments"
|
|
238
|
+
|
|
239
|
+
# append to the right of the overall binary consensus matrix
|
|
240
|
+
B = np.append(B, b, axis=1)
|
|
241
|
+
|
|
242
|
+
# remove columns in B with no cells assigned
|
|
243
|
+
# this happens if some initialised centroids do not get assigned anything
|
|
244
|
+
cols_with_no_cells = np.sum(B, axis=0) != 0
|
|
245
|
+
if not np.all(cols_with_no_cells):
|
|
246
|
+
B = B[:, np.sum(B, axis=0) != 0]
|
|
247
|
+
|
|
248
|
+
return B
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
def cluster_consensus_matrix(consensus_matrix, n_clusters, batch_size, random_state):
|
|
252
|
+
|
|
253
|
+
# check that consensus matrix has no NaN, infinity values
|
|
254
|
+
from sklearn.utils import check_array
|
|
255
|
+
consensus_matrix = check_array(consensus_matrix)
|
|
256
|
+
|
|
257
|
+
# check n_clusters
|
|
258
|
+
n_clusters = check_integer(
|
|
259
|
+
n_clusters,
|
|
260
|
+
min_val = 2,
|
|
261
|
+
max_val = consensus_matrix.shape[0],
|
|
262
|
+
var_name = 'n_clusters'
|
|
263
|
+
)
|
|
264
|
+
|
|
265
|
+
# check batch_size
|
|
266
|
+
batch_size = check_integer(
|
|
267
|
+
batch_size,
|
|
268
|
+
min_val = 10,
|
|
269
|
+
max_val = consensus_matrix.shape[0],
|
|
270
|
+
var_name = 'batch_size'
|
|
271
|
+
)
|
|
272
|
+
|
|
273
|
+
# check random state
|
|
274
|
+
from sklearn.utils import check_random_state
|
|
275
|
+
random_state = check_random_state(random_state)
|
|
276
|
+
|
|
277
|
+
from sklearn.cluster import MiniBatchKMeans
|
|
278
|
+
kmeans = MiniBatchKMeans(
|
|
279
|
+
n_clusters = n_clusters,
|
|
280
|
+
batch_size = batch_size,
|
|
281
|
+
random_state = random_state
|
|
282
|
+
)
|
|
283
|
+
kmeans.fit(consensus_matrix)
|
|
284
|
+
|
|
285
|
+
return kmeans.labels_
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
def consensus(
|
|
289
|
+
adata,
|
|
290
|
+
basis = 'pca',
|
|
291
|
+
key_added = 'sc3',
|
|
292
|
+
n_clusters = [3, 5, 10],
|
|
293
|
+
d_range = None,
|
|
294
|
+
n_runs = 5,
|
|
295
|
+
n_facility = None,
|
|
296
|
+
multiplier_facility = None,
|
|
297
|
+
batch_size = None,
|
|
298
|
+
random_state = None
|
|
299
|
+
):
|
|
300
|
+
"""\
|
|
301
|
+
Run consensus clustering to cluster cells in an AnnData object.
|
|
302
|
+
|
|
303
|
+
Parameters
|
|
304
|
+
----------
|
|
305
|
+
adata
|
|
306
|
+
Annotated data matrix.
|
|
307
|
+
n_clusters
|
|
308
|
+
Number of clusters. Default: [3,5,10]
|
|
309
|
+
d_range
|
|
310
|
+
Number of PCs. Default is 25, or the number of PCs in the
|
|
311
|
+
AnnData object, whichever is lower. Can accept a list
|
|
312
|
+
(e.g. `[15, 20, 25`]).
|
|
313
|
+
n_runs
|
|
314
|
+
Number of realisations to perform for the consensus.
|
|
315
|
+
Default is 5, recommended > 1.
|
|
316
|
+
n_facility
|
|
317
|
+
Number of microclusters. Overridden if `multiplier_facility`
|
|
318
|
+
is provided with a value.
|
|
319
|
+
multiplier_facility
|
|
320
|
+
Multiplier for microclusters. Number of microclusters
|
|
321
|
+
is calculated as this parameter multiplied by the max of
|
|
322
|
+
`n_clusters`. Default is 3.
|
|
323
|
+
batch_size
|
|
324
|
+
Batch size for k-means. Default is 100.
|
|
325
|
+
random_state
|
|
326
|
+
Random state of the algorithm.
|
|
327
|
+
|
|
328
|
+
Returns
|
|
329
|
+
-------
|
|
330
|
+
AnnData object with cluster labels written in the `.obs` dataframe.
|
|
331
|
+
|
|
332
|
+
adata.obs['sc3.{k}']
|
|
333
|
+
Labels for `n_clusters = k`.
|
|
334
|
+
"""
|
|
335
|
+
|
|
336
|
+
# check that AnnData object already has dim reduc
|
|
337
|
+
if basis in adata.obsm.keys(): X_pca = adata.obsm[basis]
|
|
338
|
+
else: error(f'{basis} does not present in your obsm slot')
|
|
339
|
+
|
|
340
|
+
# get the number of cells from row dimension
|
|
341
|
+
n_cells = X_pca.shape[0]
|
|
342
|
+
|
|
343
|
+
# check and formats n_clusters into in a list format, using default values if unprovided
|
|
344
|
+
n_clusters = check_integer_list(
|
|
345
|
+
n_clusters,
|
|
346
|
+
min_val = 2,
|
|
347
|
+
max_val = n_cells,
|
|
348
|
+
var_name = 'n_clusters'
|
|
349
|
+
)
|
|
350
|
+
|
|
351
|
+
# check d_range
|
|
352
|
+
if d_range is None:
|
|
353
|
+
d_range = [min(25, X_pca.shape[1])]
|
|
354
|
+
d_range = check_integer_list(
|
|
355
|
+
d_range,
|
|
356
|
+
min_val = 2,
|
|
357
|
+
max_val = X_pca.shape[1],
|
|
358
|
+
var_name = 'd_range'
|
|
359
|
+
)
|
|
360
|
+
|
|
361
|
+
# check n_runs
|
|
362
|
+
n_runs = check_integer(n_runs, min_val = 1, var_name = "n_runs")
|
|
363
|
+
|
|
364
|
+
# check batch_size
|
|
365
|
+
if batch_size is None:
|
|
366
|
+
batch_size=min(100, adata.shape[0])
|
|
367
|
+
if isinstance(batch_size, int):
|
|
368
|
+
if batch_size > n_cells:
|
|
369
|
+
error("batch size for k-means must be smaller than number of cells.")
|
|
370
|
+
else: error("batch size must be positive integer value (default: 100)")
|
|
371
|
+
|
|
372
|
+
# check random state
|
|
373
|
+
random_state = check_random_state(random_state)
|
|
374
|
+
|
|
375
|
+
# determine number of facilities to use
|
|
376
|
+
if n_facility is not None:
|
|
377
|
+
warning(f"n_facility set to {n_facility}, ignoring multiplier_facility parameter")
|
|
378
|
+
else:
|
|
379
|
+
if multiplier_facility is None:
|
|
380
|
+
info(f"multiplier_facility not set, using default value of 3")
|
|
381
|
+
multiplier_facility = 3
|
|
382
|
+
|
|
383
|
+
# use multiplier value to calculate
|
|
384
|
+
n_facility = max(n_clusters) * multiplier_facility
|
|
385
|
+
|
|
386
|
+
if n_facility >= n_cells:
|
|
387
|
+
n_facility = n_cells - 1
|
|
388
|
+
|
|
389
|
+
info(f"number of facilities calculated as {n_facility}")
|
|
390
|
+
|
|
391
|
+
n_facility = check_integer(
|
|
392
|
+
n_facility,
|
|
393
|
+
min_val = 2,
|
|
394
|
+
max_val = n_cells,
|
|
395
|
+
var_name = 'n_facility'
|
|
396
|
+
)
|
|
397
|
+
|
|
398
|
+
# run over many different trials
|
|
399
|
+
trials_dict = run_trials_minibatch_kmeans(
|
|
400
|
+
data = X_pca,
|
|
401
|
+
n_clusters = n_facility,
|
|
402
|
+
d_range = d_range,
|
|
403
|
+
n_runs = n_runs,
|
|
404
|
+
batch_size = batch_size,
|
|
405
|
+
random_state = random_state
|
|
406
|
+
)
|
|
407
|
+
|
|
408
|
+
# write the individual trials into AnnData object
|
|
409
|
+
adata.uns[f'{key_added}.trials'] = trials_dict
|
|
410
|
+
|
|
411
|
+
# run different number of clusters
|
|
412
|
+
for K in n_clusters:
|
|
413
|
+
consensus_dict = combine_facilities(
|
|
414
|
+
dict_object = trials_dict,
|
|
415
|
+
K = K,
|
|
416
|
+
n_facility = n_facility,
|
|
417
|
+
batch_size = batch_size,
|
|
418
|
+
random_state = random_state
|
|
419
|
+
)
|
|
420
|
+
|
|
421
|
+
B = convert_dict_into_binary_matrix(
|
|
422
|
+
dict_object = consensus_dict,
|
|
423
|
+
true_n_clusters = K,
|
|
424
|
+
true_n_cells = n_cells
|
|
425
|
+
)
|
|
426
|
+
|
|
427
|
+
cell_labels = cluster_consensus_matrix(
|
|
428
|
+
consensus_matrix = B,
|
|
429
|
+
n_clusters = K,
|
|
430
|
+
batch_size = batch_size,
|
|
431
|
+
random_state = random_state
|
|
432
|
+
)
|
|
433
|
+
|
|
434
|
+
# write results into AnnData object
|
|
435
|
+
adata.obs[f'{key_added}.{K}'] = cell_labels
|
|
436
|
+
adata.obs[f'{key_added}.{K}'] = adata.obs[f'{key_added}.{K}'].astype('str').astype('category')
|
|
437
|
+
|
|
438
|
+
return adata
|
|
@@ -53,13 +53,14 @@ def serial_matrix(dist, method = "ward", seed = 42):
|
|
|
53
53
|
'''
|
|
54
54
|
np.random.seed(seed)
|
|
55
55
|
|
|
56
|
-
N = len(dist)
|
|
57
56
|
flat_dist_mat = squareform(dist)
|
|
58
|
-
|
|
57
|
+
N = len(flat_dist_mat)
|
|
58
|
+
|
|
59
|
+
res_linkage = linkage(dist, method = method, preserve_input = True)
|
|
59
60
|
res_order = seriation(res_linkage, N, N + N-2)
|
|
60
|
-
seriated_dist = np.zeros((N,N))
|
|
61
|
+
seriated_dist = np.zeros((N, N))
|
|
61
62
|
a,b = np.triu_indices(N, k = 1)
|
|
62
|
-
seriated_dist[a,b] =
|
|
63
|
+
seriated_dist[a,b] = flat_dist_mat[ [res_order[i] for i in a], [res_order[j] for j in b]]
|
|
63
64
|
seriated_dist[b,a] = seriated_dist[a,b]
|
|
64
65
|
|
|
65
66
|
return seriated_dist, res_order, res_linkage
|
|
@@ -11,6 +11,7 @@ from exprmat.lr.utils import default_params as V
|
|
|
11
11
|
from exprmat.lr.utils import default_primary_columns as P
|
|
12
12
|
from exprmat.ansi import error, warning, info
|
|
13
13
|
from exprmat.data.finders import basepath
|
|
14
|
+
from exprmat.data.orthologs import get_orthologs_symbol
|
|
14
15
|
|
|
15
16
|
|
|
16
17
|
def select_resource(taxa, resource_name: str = V.resource_name) -> DataFrame:
|
|
@@ -48,9 +49,10 @@ def handle_resource(
|
|
|
48
49
|
# to the destination (currently handling) taxa
|
|
49
50
|
if source_taxa != destination_taxa:
|
|
50
51
|
resource = translate_resource(
|
|
51
|
-
resource, map_df =
|
|
52
|
+
resource, map_df = get_orthologs_symbol(
|
|
52
53
|
taxa = source_taxa, destination = destination_taxa,
|
|
53
|
-
min_evidence = min_evidence, columns = None
|
|
54
|
+
# min_evidence = min_evidence, columns = None,
|
|
55
|
+
suppress_many_to_one = False, suppress_one_to_many = False
|
|
54
56
|
), columns = ['ligand', 'receptor'], replace = True,
|
|
55
57
|
|
|
56
58
|
# here, we will be harsher and only keep mappings that don't map to more
|
|
@@ -125,12 +127,12 @@ def translate_column(resource, map_df, column, replace=True, one_to_many = 1,):
|
|
|
125
127
|
|
|
126
128
|
if not isinstance(one_to_many, int):
|
|
127
129
|
error("`one_to_many` should be a positive integer.")
|
|
128
|
-
if ['source', '
|
|
129
|
-
error("The `map_df` data frame must have two columns named 'source' and '
|
|
130
|
+
if ['source', 'dest'] != map_df.columns.tolist():
|
|
131
|
+
error("The `map_df` data frame must have two columns named 'source' and 'dest'.")
|
|
130
132
|
|
|
131
133
|
# get orthologs
|
|
132
134
|
map_df = map_df.set_index("source")
|
|
133
|
-
map_dict = map_df.groupby(level = 0)["
|
|
135
|
+
map_dict = map_df.groupby(level = 0)["dest"].apply(list).to_dict()
|
|
134
136
|
map_data = generate_orthologs(resource, column, map_dict, one_to_many)
|
|
135
137
|
|
|
136
138
|
# join orthologs
|
|
@@ -157,37 +159,3 @@ def translate_resource(resource, map_df, columns = ['ligand', 'receptor'], **kwa
|
|
|
157
159
|
resource = translate_column(resource, map_df, column, **kwargs)
|
|
158
160
|
return resource
|
|
159
161
|
|
|
160
|
-
|
|
161
|
-
def get_orthologs(taxa, destination, min_evidence = 3, columns = None ):
|
|
162
|
-
"""
|
|
163
|
-
HCOP is a composite database combining data from various orthology resources.
|
|
164
|
-
It provides a comprehensive set of orthologs among human, mouse, and rat, among many other species.
|
|
165
|
-
|
|
166
|
-
If you use this function, please reference the original HCOP papers:
|
|
167
|
-
- Eyre, T.A., Wright, M.W., Lush, M.J. and Bruford, E.A., 2007. HCOP: a searchable database of
|
|
168
|
-
human orthology predictions. Briefings in bioinformatics, 8(1), pp.2-5.
|
|
169
|
-
- Yates, B., Gray, K.A., Jones, T.E. and Bruford, E.A., 2021. Updates to HCOP: the HGNC comparison
|
|
170
|
-
of orthology predictions tool. Briefings in Bioinformatics, 22(6), p.bbab155.
|
|
171
|
-
|
|
172
|
-
For more information, please visit the HCOP website: https://www.genenames.org/tools/hcop/,
|
|
173
|
-
or alternatively check the bulk download FTP links page: https://ftp.ebi.ac.uk/pub/databases/genenames/hcop/
|
|
174
|
-
"""
|
|
175
|
-
|
|
176
|
-
filename = os.path.join(basepath, taxa, 'orthologs', destination + '.tsv.gz')
|
|
177
|
-
if not os.path.exists(filename):
|
|
178
|
-
error(f'the orthologs of requested species `{destination}` (from {taxa}) is not registered in database.')
|
|
179
|
-
|
|
180
|
-
mapping = read_table(filename, sep = "\t")
|
|
181
|
-
mapping['evidence'] = mapping['support'].apply(lambda x: len(x.split(",")))
|
|
182
|
-
mapping = mapping[mapping['evidence'] >= min_evidence]
|
|
183
|
-
|
|
184
|
-
if columns is not None:
|
|
185
|
-
mapping = mapping[columns]
|
|
186
|
-
else:
|
|
187
|
-
columns = []
|
|
188
|
-
for x in mapping.columns.tolist():
|
|
189
|
-
if x.endswith('_symbol'): columns.append(x)
|
|
190
|
-
mapping = mapping[columns]
|
|
191
|
-
|
|
192
|
-
mapping.columns.names = ['source', 'target']
|
|
193
|
-
return mapping
|