exprmat 0.2.79__tar.gz → 0.2.81__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.2.79 → exprmat-0.2.81}/PKG-INFO +1 -1
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/__init__.py +3 -0
- exprmat-0.2.81/exprmat/data/malig.py +16 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/data/signature.py +4 -1
- exprmat-0.2.81/exprmat/malig/__init__.py +45 -0
- exprmat-0.2.81/exprmat/malig/classifier.py +439 -0
- exprmat-0.2.81/exprmat/malig/scoring.py +156 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/reader/experiment.py +3 -3
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/reader/rna/__init__.py +9 -2
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/reader/rna/interaction.py +1 -1
- exprmat-0.2.81/exprmat/reader/rna/malig.py +119 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/reader/rna/markers.py +16 -1
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/reader/rna/repertoire.py +7 -7
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/reader/rna/trajectory.py +5 -1
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/reduction/nn.py +2 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/wgcna/__init__.py +3 -3
- {exprmat-0.2.79 → exprmat-0.2.81}/pyproject.toml +1 -1
- {exprmat-0.2.79 → exprmat-0.2.81}/Cargo.lock +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/Cargo.toml +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/ansi.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/clustering/__init__.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/clustering/cnmf.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/clustering/dbscan.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/clustering/gating.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/clustering/kmeans.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/clustering/leiden.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/clustering/nmf.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/clustering/rogue.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/clustering/sc3.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/clustering/seriation.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/clustering/spectral.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/clustering/utils.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/cnv/__init__.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/cnv/cnvscore.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/cnv/infercnv.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/configuration.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/data/__init__.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/data/cistarget.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/data/cre.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/data/decoupler.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/data/finders.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/data/geneset.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/data/icnet.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/data/io.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/data/lr.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/data/orthologs.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/data/presets.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/data/repertoire.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/data/tf.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/deconv/__init__.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/deconv/deconv.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/deconv/simulation.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/deconv/tangram/__init__.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/deconv/tangram/mapping.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/deconv/tangram/optimizer.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/deconv/tangram/spatial.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/deconv/tangram/utils.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/descriptive/__init__.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/descriptive/aggregate.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/descriptive/atac.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/descriptive/aucell.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/descriptive/composition.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/descriptive/covar.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/descriptive/de.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/descriptive/geneset.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/descriptive/gse.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/descriptive/kde.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/descriptive/recovery.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/descriptive/sccoda.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/descriptive/summary.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/descriptive/tcr.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/deseq/dataset.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/deseq/gridsearch.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/deseq/inference.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/deseq/preprocessing.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/deseq/stats.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/deseq/utils.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/domain/__init__.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/domain/deepst/__init__.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/domain/deepst/adjacency.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/domain/deepst/api.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/domain/deepst/augment.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/domain/deepst/image_features.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/domain/deepst/model.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/domain/deepst/runner.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/domain/deepst/trainer.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/domain/spagcn/__init__.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/domain/spagcn/adjacency.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/domain/spagcn/api.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/domain/spagcn/layers.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/domain/spagcn/models.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/domain/spagcn/morans.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/domain/spagcn/spagcn.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/domain/spagcn/svg.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/domain/spatialde/__init__.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/domain/spatialde/api.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/domain/spatialde/kernels.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/domain/spatialde/score_test.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/dynamics/__init__.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/dynamics/generank.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/dynamics/linreg.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/dynamics/moments.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/dynamics/optimization.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/dynamics/parallel.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/dynamics/preprocess.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/dynamics/pseudotime.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/dynamics/transition.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/dynamics/utils.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/dynamics/velocity.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/grn/__init__.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/grn/infergrn.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/grn/modules.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/grn/prune.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/grn/regressors.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/grn/utils.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/help.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/image/__init__.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/image/augment.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/image/axis.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/image/channel.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/image/compensation.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/image/density.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/image/segmentation.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/image/tissue.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/image/transform.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/lr/__init__.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/lr/aggregate.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/lr/cellnest/__init__.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/lr/cellnest/api.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/lr/cellnest/gat.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/lr/cellnest/intra.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/lr/cellnest/model.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/lr/cellnest/plotting.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/lr/cellnest/postprocess.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/lr/cellnest/preprocess.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/lr/cellnest/relay.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/lr/cellnest/stats.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/lr/cellnest/train.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/lr/cellnest/utils.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/lr/icnet/__init__.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/lr/icnet/construction.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/lr/icnet/importance.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/lr/icnet/ligand.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/lr/icnet/metrics.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/lr/icnet/pagerank.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/lr/method.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/lr/methods/__init__.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/lr/methods/cellchat.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/lr/methods/cellphonedb.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/lr/methods/connectome.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/lr/methods/geomean.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/lr/methods/logfc.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/lr/methods/natmi.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/lr/methods/rank_aggregate.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/lr/methods/scseqcomm.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/lr/methods/singlecellsignalr.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/lr/pipeline.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/lr/preprocess.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/lr/resources.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/lr/utils.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/metacell/__init__.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/metacell/engine.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/metacell/model.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/metacell/utils.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/nmf/__init__.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/nmf/methods/factorization/__init__.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/nmf/methods/factorization/bd.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/nmf/methods/factorization/bmf.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/nmf/methods/factorization/icm.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/nmf/methods/factorization/lfnmf.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/nmf/methods/factorization/lsnmf.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/nmf/methods/factorization/nmf.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/nmf/methods/factorization/nsnmf.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/nmf/methods/factorization/pmf.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/nmf/methods/factorization/pmfcc.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/nmf/methods/factorization/psmf.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/nmf/methods/factorization/sepnmf.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/nmf/methods/factorization/snmf.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/nmf/methods/factorization/snmnmf.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/nmf/methods/seeding/__init__.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/nmf/methods/seeding/fixed.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/nmf/methods/seeding/nndsvd.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/nmf/methods/seeding/random.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/nmf/methods/seeding/random_c.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/nmf/methods/seeding/random_vcol.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/nmf/models/__init__.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/nmf/models/mf_fit.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/nmf/models/mf_track.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/nmf/models/nmf.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/nmf/models/nmf_mm.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/nmf/models/nmf_ns.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/nmf/models/nmf_std.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/nmf/models/smf.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/nmf/utils/__init__.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/nmf/utils/linalg.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/nmf/utils/utils.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/parser/__init__.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/parser/converter.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/parser/rds.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/parser/seurat.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/peaks/__init__.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/peaks/callpeak.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/peaks/common.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/peaks/coverage.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/peaks/footprint.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/peaks/idr/__init__.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/peaks/idr/constants.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/peaks/idr/idr.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/peaks/idr/invcdf.pyx +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/peaks/idr/optimization.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/peaks/idr/utils.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/peaks/linkage.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/peaks/motif.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/peaks/sequence.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/plotting/__init__.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/plotting/atac.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/plotting/cnmf.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/plotting/cnv.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/plotting/data/A.pk +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/plotting/data/B.pk +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/plotting/data/C.pk +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/plotting/data/D.pk +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/plotting/data/E.pk +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/plotting/data/F.pk +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/plotting/data/G.pk +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/plotting/data/H.pk +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/plotting/data/I.pk +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/plotting/data/J.pk +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/plotting/data/K.pk +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/plotting/data/L.pk +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/plotting/data/M.pk +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/plotting/data/N.pk +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/plotting/data/O.pk +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/plotting/data/P.pk +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/plotting/data/Q.pk +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/plotting/data/R.pk +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/plotting/data/S.pk +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/plotting/data/T.pk +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/plotting/data/U.pk +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/plotting/data/V.pk +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/plotting/data/W.pk +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/plotting/data/X.pk +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/plotting/data/Y.pk +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/plotting/data/Z.pk +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/plotting/de.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/plotting/expression.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/plotting/gse.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/plotting/icnet.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/plotting/knee.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/plotting/lr.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/plotting/matrix.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/plotting/milestone.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/plotting/network.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/plotting/order.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/plotting/palettes.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/plotting/proximity.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/plotting/sankey.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/plotting/sequence.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/plotting/summary.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/plotting/track.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/plotting/trajectory.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/plotting/utils.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/plotting/velocity.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/plotting/wgcna.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/preprocessing/__init__.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/preprocessing/background/__init__.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/preprocessing/background/correction.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/preprocessing/background/dirichlet_multinomial.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/preprocessing/background/emptydrops.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/preprocessing/background/estimation.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/preprocessing/background/multinomial.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/preprocessing/background/sgt.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/preprocessing/background/soupx.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/preprocessing/doublets/__init__.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/preprocessing/doublets/composite.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/preprocessing/doublets/ddetect.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/preprocessing/doublets/scrublet.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/preprocessing/emptydrops.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/preprocessing/filter.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/preprocessing/impute/__init__.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/preprocessing/impute/magic.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/preprocessing/integrate.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/preprocessing/linear.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/preprocessing/normal.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/preprocessing/plot.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/preprocessing/qc.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/preprocessing/sctransform/__init__.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/preprocessing/sctransform/estimate.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/preprocessing/sctransform/ksmooth.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/preprocessing/sctransform/residual.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/preprocessing/sctransform/transform.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/preprocessing/sparse.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/preprocessing/uniform.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/reader/__init__.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/reader/accessor.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/reader/atac/__init__.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/reader/atac/derive.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/reader/atac/peaks.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/reader/atac/preprocessing.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/reader/cite/__init__.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/reader/cite/preprocessing.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/reader/conversions.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/reader/data-structure.txt +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/reader/general/__init__.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/reader/history.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/reader/introspect.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/reader/introspective.txt +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/reader/matcher.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/reader/metadata.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/reader/rna/atlas.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/reader/rna/bulk.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/reader/rna/cnv.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/reader/rna/geneset.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/reader/rna/getter.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/reader/rna/impute.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/reader/rna/nmf.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/reader/rna/proportion.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/reader/rna/qc.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/reader/rna/reduction.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/reader/rna/summarize.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/reader/schema.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/reader/spatial/__init__.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/reader/spatial/classifier.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/reader/spatial/coordinates.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/reader/spatial/deconv.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/reader/spatial/density.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/reader/spatial/domains.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/reader/spatial/getter.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/reader/spatial/graph.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/reader/spatial/image.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/reader/spatial/lr.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/reader/spatial/proximity.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/reader/spatial/qc.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/reader/spatial/segmentation.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/reader/spatial/snn.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/reader/spatial/tmap.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/reader/spatial/transform.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/reader/static.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/reader/updater.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/reduction/__init__.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/reduction/diffmap.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/reduction/forceatlas.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/reduction/mde.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/reduction/outliers.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/reduction/pca.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/reduction/plot.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/reduction/scvi.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/reduction/spectral.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/reduction/tsne.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/reduction/umap.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/reduction/wnn/__init__.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/reduction/wnn/landmarks.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/reduction/wnn/plan.md +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/reduction/wnn/projection.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/reduction/wnn/refinement.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/reduction/wnn/sampling.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/reduction/wnn/umap_landmarks.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/repertoire/__init__.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/repertoire/analysis.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/repertoire/convergence.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/repertoire/distance.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/repertoire/plotting.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/repertoire/reference.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/signature/__init__.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/signature/datatype.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/signature/download.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/signature/log.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/signature/method.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/signature/methods/__init__.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/signature/methods/aucell.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/signature/methods/consensus.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/signature/methods/decouple.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/signature/methods/gsea.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/signature/methods/gsva.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/signature/methods/mdt.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/signature/methods/mlm.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/signature/methods/ora.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/signature/methods/pv.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/signature/methods/query_set.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/signature/methods/registry.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/signature/methods/run.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/signature/methods/udt.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/signature/methods/ulm.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/signature/methods/viper.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/signature/methods/waggr.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/signature/methods/zscore.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/signature/odeps.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/signature/plotter.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/signature/plotting/__init__.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/signature/plotting/barplot.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/signature/plotting/dotplot.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/signature/plotting/filter_by_expr.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/signature/plotting/filter_by_prop.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/signature/plotting/filter_samples.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/signature/plotting/leading_edge.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/signature/plotting/network.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/signature/plotting/obsbar.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/signature/plotting/obsm.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/signature/plotting/order.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/signature/plotting/order_targets.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/signature/plotting/source_targets.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/signature/plotting/volcano.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/signature/utils/__init__.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/signature/utils/anndata.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/signature/utils/data.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/signature/utils/net.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/signature/utils/rankby_group.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/signature/utils/rankby_obsm.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/signature/utils/rankby_order.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/spatial/__init__.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/spatial/classifier.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/spatial/hd.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/spatial/interac.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/spatial/ligrec.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/spatial/mif.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/spatial/nhood.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/spatial/niche.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/spatial/ometiff.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/spatial/pattern.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/spatial/ripley.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/spatial/snn.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/spatial/tmap.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/spatial/utils.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/spatial/visium.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/spatial/xenium.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/trajectory/__init__.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/trajectory/cytotrace.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/trajectory/elpi.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/trajectory/pcurve.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/trajectory/pseudotime.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/trajectory/root.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/trajectory/trace.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/transfer/__init__.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/transfer/atlas.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/utils.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/exprmat/wgcna/core.py +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/license +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/readme.md +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/snapatac2/Cargo.toml +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/snapatac2/license +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/snapatac2/readme +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/snapatac2/src/call_peaks.rs +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/snapatac2/src/embedding.rs +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/snapatac2/src/export.rs +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/snapatac2/src/knn.rs +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/snapatac2/src/lib.rs +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/snapatac2/src/motif.rs +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/snapatac2/src/network.rs +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/snapatac2/src/preprocessing.rs +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/snapatac2/src/utils/anndata.rs +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/snapatac2/src/utils.rs +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/snapatac2-core/Cargo.toml +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/snapatac2-core/src/embedding.rs +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/snapatac2-core/src/export.rs +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/snapatac2-core/src/feature_count/counter.rs +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/snapatac2-core/src/feature_count/data_iter.rs +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/snapatac2-core/src/feature_count/matrix.rs +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/snapatac2-core/src/feature_count/mod.rs +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/snapatac2-core/src/genome.rs +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/snapatac2-core/src/lib.rs +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/snapatac2-core/src/motif.rs +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/snapatac2-core/src/network.rs +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/snapatac2-core/src/preprocessing/bam/flagstat.rs +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/snapatac2-core/src/preprocessing/bam/header.rs +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/snapatac2-core/src/preprocessing/bam/mark_duplicates.rs +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/snapatac2-core/src/preprocessing/bam.rs +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/snapatac2-core/src/preprocessing/import.rs +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/snapatac2-core/src/preprocessing/mod.rs +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/snapatac2-core/src/preprocessing/qc.rs +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/snapatac2-core/src/utils/knn.rs +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/snapatac2-core/src/utils/mod.rs +0 -0
- {exprmat-0.2.79 → exprmat-0.2.81}/snapatac2-core/src/utils/similarity.rs +0 -0
|
@@ -106,6 +106,9 @@ default_finders = [
|
|
|
106
106
|
'exprmat.config',
|
|
107
107
|
'.exprmat.config',
|
|
108
108
|
'.exprmatrc',
|
|
109
|
+
_os.path.join(str(_os.environ.get("CONDA_PREFIX") or ''), 'exprmat.config'),
|
|
110
|
+
_os.path.join(str(_os.environ.get("CONDA_PREFIX") or ''), '.exprmat.config'),
|
|
111
|
+
_os.path.join(str(_os.environ.get("CONDA_PREFIX") or ''), '.exprmatrc'),
|
|
109
112
|
_os.path.join(str(_pathlib.Path.home()), 'exprmat.config'),
|
|
110
113
|
_os.path.join(str(_pathlib.Path.home()), '.exprmat.config'),
|
|
111
114
|
_os.path.join(str(_pathlib.Path.home()), '.exprmatrc')
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
|
|
2
|
+
from pandas import read_table, isnull
|
|
3
|
+
import pandas as pd
|
|
4
|
+
from numpy import unique
|
|
5
|
+
import numpy as np
|
|
6
|
+
import os
|
|
7
|
+
import itertools
|
|
8
|
+
from pandas import DataFrame
|
|
9
|
+
|
|
10
|
+
from exprmat.ansi import error, warning, info
|
|
11
|
+
from exprmat.data.finders import basepath
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def get_malignancy_model_folder(taxa) -> DataFrame:
|
|
15
|
+
resource_path = os.path.join(basepath, taxa, 'malig')
|
|
16
|
+
return resource_path
|
|
@@ -25,7 +25,10 @@ def convert(genes):
|
|
|
25
25
|
return frozendict(zip(genes, repeat(1.0)))
|
|
26
26
|
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
# `signature` must be hashable because `genes` and `weights` are memoized
|
|
29
|
+
# properties (`cytoolz.memoize` caches on the instance itself). without a
|
|
30
|
+
# generated `__hash__` any access to `signature.genes` raised a `TypeError`.
|
|
31
|
+
@attr.s(hash = True)
|
|
29
32
|
class signature():
|
|
30
33
|
"""
|
|
31
34
|
Gene signatures, i.e. a set of genes that are biologically related.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"""
|
|
2
|
+
malignancy inference.
|
|
3
|
+
|
|
4
|
+
Malignant cells are distinguished from their normal counterparts using a
|
|
5
|
+
pretrained pan-cancer classifier, ported from `scMalignantFinder`
|
|
6
|
+
(https://github.com/Jonyyqn/scMalignantFinder, Yu et al., Commun Biol 2025).
|
|
7
|
+
Only human cancers can be predicted.
|
|
8
|
+
|
|
9
|
+
Only the inference part of the upstream package is included:
|
|
10
|
+
|
|
11
|
+
* :mod:`.classifier` -- pretrained cell-level (gross) malignancy inference.
|
|
12
|
+
* :mod:`.scoring` -- AUCell gene set scoring backed by the in-package
|
|
13
|
+
implementation in :mod:`exprmat.descriptive.aucell`.
|
|
14
|
+
|
|
15
|
+
Model training, scATOMIC cell type annotation (R) and spatial region
|
|
16
|
+
identification are not included, and no R, `scAtomic`, `pyscenic` or `ctxcore`
|
|
17
|
+
dependency is required.
|
|
18
|
+
|
|
19
|
+
The pretrained model (``model.joblib``) and its ordered feature list
|
|
20
|
+
(``ordered_feature.tsv``) are distributed separately by the upstream authors at
|
|
21
|
+
https://zenodo.org/records/17888140. Place both files in one directory and pass
|
|
22
|
+
it as ``pretrain_dir``.
|
|
23
|
+
|
|
24
|
+
Examples
|
|
25
|
+
--------
|
|
26
|
+
>>> from exprmat.malig import predict_malignancy
|
|
27
|
+
>>> adata = predict_malignancy(adata, pretrain_dir = 'pretrained_model')
|
|
28
|
+
>>> adata.obs[['malig', 'prob.malig']].head()
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
from exprmat.malig.classifier import (
|
|
32
|
+
malignancy_inference,
|
|
33
|
+
predict_malignancy,
|
|
34
|
+
load_ordered_features,
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
from exprmat.malig.scoring import aucell_score
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
__all__ = [
|
|
41
|
+
'malignancy_inference',
|
|
42
|
+
'predict_malignancy',
|
|
43
|
+
'load_ordered_features',
|
|
44
|
+
'aucell_score',
|
|
45
|
+
]
|
|
@@ -0,0 +1,439 @@
|
|
|
1
|
+
"""
|
|
2
|
+
cell-level (gross) malignancy inference with a pretrained model.
|
|
3
|
+
|
|
4
|
+
This module ports the inference half of `scMalignantFinder`
|
|
5
|
+
(https://github.com/Jonyyqn/scMalignantFinder, Yu et al., Commun Biol 2025).
|
|
6
|
+
Only the pretrained malignancy classifier is implemented. model training,
|
|
7
|
+
scATOMIC cell type annotation (which requires R) and spatial region
|
|
8
|
+
identification are intentionally left out, so this module has no dependency on
|
|
9
|
+
R, `scAtomic`, `pyscenic` or `ctxcore`.
|
|
10
|
+
|
|
11
|
+
.. warning::
|
|
12
|
+
The released model was trained on human pan-cancer signatures and is only
|
|
13
|
+
suitable for **human** data. Running it on mouse data, including after any
|
|
14
|
+
ortholog conversion, is strongly discouraged: malignant versus normal
|
|
15
|
+
expression programs are very unlikely to be conserved between species.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
import os
|
|
19
|
+
from typing import Iterable
|
|
20
|
+
|
|
21
|
+
import joblib
|
|
22
|
+
import numpy as np
|
|
23
|
+
import pandas as pd
|
|
24
|
+
import scipy.sparse as sp
|
|
25
|
+
from anndata import AnnData
|
|
26
|
+
|
|
27
|
+
from exprmat.ansi import error, info, warning
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
MODEL_FILENAME = 'model.joblib'
|
|
31
|
+
FEATURE_FILENAME = 'ordered_feature.tsv'
|
|
32
|
+
|
|
33
|
+
NORMAL = 'Normal'
|
|
34
|
+
MALIGNANT = 'Malignant'
|
|
35
|
+
|
|
36
|
+
DEFAULT_TARGET_SUM = 1e4
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def load_ordered_features(feature_path: str) -> list[str]:
|
|
40
|
+
"""
|
|
41
|
+
Load an ordered feature list, one gene symbol per line.
|
|
42
|
+
|
|
43
|
+
The pretrained model expects the expression matrix to be arranged in exactly
|
|
44
|
+
this order. Duplicated entries are kept as they are, since the model was fit
|
|
45
|
+
on this exact layout.
|
|
46
|
+
|
|
47
|
+
Parameters
|
|
48
|
+
----------
|
|
49
|
+
feature_path
|
|
50
|
+
Path to the feature list, usually ``ordered_feature.tsv``.
|
|
51
|
+
|
|
52
|
+
Returns
|
|
53
|
+
-------
|
|
54
|
+
The ordered list of feature (gene) names.
|
|
55
|
+
"""
|
|
56
|
+
|
|
57
|
+
if not os.path.isfile(feature_path):
|
|
58
|
+
error(f'feature list not found: {feature_path}')
|
|
59
|
+
|
|
60
|
+
with open(feature_path, 'r') as f:
|
|
61
|
+
features = [line.strip() for line in f if line.strip()]
|
|
62
|
+
|
|
63
|
+
if len(features) == 0:
|
|
64
|
+
error(f'feature list is empty: {feature_path}')
|
|
65
|
+
|
|
66
|
+
return features
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def _resolve_pretrain_files(
|
|
70
|
+
pretrain_dir: str | None = None,
|
|
71
|
+
model_path: str | None = None,
|
|
72
|
+
feature_path: str | None = None,
|
|
73
|
+
) -> tuple[str, str]:
|
|
74
|
+
|
|
75
|
+
if pretrain_dir is not None:
|
|
76
|
+
if model_path is None:
|
|
77
|
+
model_path = os.path.join(pretrain_dir, MODEL_FILENAME)
|
|
78
|
+
if feature_path is None:
|
|
79
|
+
feature_path = os.path.join(pretrain_dir, FEATURE_FILENAME)
|
|
80
|
+
|
|
81
|
+
if model_path is None or feature_path is None:
|
|
82
|
+
error(
|
|
83
|
+
'a pretrained model is required for inference. provide `pretrain_dir` '
|
|
84
|
+
f'(a directory containing `{MODEL_FILENAME}` and `{FEATURE_FILENAME}`), '
|
|
85
|
+
'or provide both `model_path` and `feature_path`.'
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
return model_path, feature_path
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def _expression_matrix(
|
|
92
|
+
adata: AnnData,
|
|
93
|
+
use_raw: bool = False,
|
|
94
|
+
layer: str | None = None,
|
|
95
|
+
):
|
|
96
|
+
|
|
97
|
+
if use_raw and layer is not None:
|
|
98
|
+
error('`use_raw = True` and `layer` cannot be used together.')
|
|
99
|
+
|
|
100
|
+
if use_raw:
|
|
101
|
+
if adata.raw is None:
|
|
102
|
+
error('`use_raw = True`, but `adata.raw` is not available.')
|
|
103
|
+
X = adata.raw.X
|
|
104
|
+
var_names = adata.raw.var_names
|
|
105
|
+
elif layer is not None:
|
|
106
|
+
if layer not in adata.layers:
|
|
107
|
+
error(f'layer `{layer}` not found in `adata.layers`.')
|
|
108
|
+
X = adata.layers[layer]
|
|
109
|
+
var_names = adata.var_names
|
|
110
|
+
else:
|
|
111
|
+
X = adata.X
|
|
112
|
+
var_names = adata.var_names
|
|
113
|
+
|
|
114
|
+
if X is None:
|
|
115
|
+
error('the expression matrix is empty.')
|
|
116
|
+
if X.shape[0] != adata.n_obs:
|
|
117
|
+
error('the expression matrix does not match `adata.n_obs`.')
|
|
118
|
+
|
|
119
|
+
return X, var_names
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def _feature_positions(
|
|
123
|
+
features: Iterable[str],
|
|
124
|
+
var_names: Iterable[str],
|
|
125
|
+
) -> tuple[np.ndarray, np.ndarray, list[str]]:
|
|
126
|
+
"""
|
|
127
|
+
Match the ordered model features against the variables of the expression
|
|
128
|
+
matrix. Returns the column positions in the output matrix, the corresponding
|
|
129
|
+
column indices in the expression matrix, and the missing feature names.
|
|
130
|
+
"""
|
|
131
|
+
|
|
132
|
+
lookup: dict[str, int] = {}
|
|
133
|
+
for i, name in enumerate(var_names):
|
|
134
|
+
# keep the first occurrence, as `var_names_make_unique` does upstream.
|
|
135
|
+
lookup.setdefault(str(name), i)
|
|
136
|
+
|
|
137
|
+
cols: list[int] = []
|
|
138
|
+
idx: list[int] = []
|
|
139
|
+
missing: list[str] = []
|
|
140
|
+
for j, name in enumerate(features):
|
|
141
|
+
i = lookup.get(str(name))
|
|
142
|
+
if i is None:
|
|
143
|
+
missing.append(name)
|
|
144
|
+
else:
|
|
145
|
+
cols.append(j)
|
|
146
|
+
idx.append(i)
|
|
147
|
+
|
|
148
|
+
return (
|
|
149
|
+
np.asarray(cols, dtype = np.intp),
|
|
150
|
+
np.asarray(idx, dtype = np.intp),
|
|
151
|
+
missing,
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
class malignancy_inference():
|
|
156
|
+
"""
|
|
157
|
+
Pretrained cell-level (gross) malignancy inference.
|
|
158
|
+
|
|
159
|
+
The classifier is trained on pan-cancer signatures by the
|
|
160
|
+
`scMalignantFinder` authors. This class only performs inference with the
|
|
161
|
+
released pretrained model: model training is not supported.
|
|
162
|
+
|
|
163
|
+
Parameters
|
|
164
|
+
----------
|
|
165
|
+
pretrain_dir
|
|
166
|
+
Directory containing ``model.joblib`` and ``ordered_feature.tsv``.
|
|
167
|
+
model_path
|
|
168
|
+
Explicit path to a pretrained ``model.joblib``. Overrides
|
|
169
|
+
``pretrain_dir`` when given.
|
|
170
|
+
feature_path
|
|
171
|
+
Explicit path to the ordered feature list. Overrides ``pretrain_dir``
|
|
172
|
+
when given.
|
|
173
|
+
normalize
|
|
174
|
+
Whether to apply library size normalization (to ``target_sum``) before
|
|
175
|
+
prediction. No log transformation is applied, as in the upstream
|
|
176
|
+
package. Set to ``False`` if the data are already normalized.
|
|
177
|
+
use_raw
|
|
178
|
+
Use ``adata.raw.X`` instead of ``adata.X``.
|
|
179
|
+
target_sum
|
|
180
|
+
Target total count per cell when ``normalize = True``.
|
|
181
|
+
verbose
|
|
182
|
+
Print information about the loaded model and missing features.
|
|
183
|
+
|
|
184
|
+
Examples
|
|
185
|
+
--------
|
|
186
|
+
>>> from exprmat.malig import malignancy_inference
|
|
187
|
+
>>> model = malignancy_inference(pretrain_dir = 'pretrained_model')
|
|
188
|
+
>>> model.load()
|
|
189
|
+
>>> adata = model.predict(adata)
|
|
190
|
+
"""
|
|
191
|
+
|
|
192
|
+
def __init__(
|
|
193
|
+
self,
|
|
194
|
+
pretrain_dir: str | None = None,
|
|
195
|
+
model_path: str | None = None,
|
|
196
|
+
feature_path: str | None = None,
|
|
197
|
+
normalize: bool = True,
|
|
198
|
+
use_raw: bool = False,
|
|
199
|
+
target_sum: float = DEFAULT_TARGET_SUM,
|
|
200
|
+
verbose: bool = True,
|
|
201
|
+
):
|
|
202
|
+
|
|
203
|
+
self.pretrain_dir = pretrain_dir
|
|
204
|
+
self.model_path = model_path
|
|
205
|
+
self.feature_path = feature_path
|
|
206
|
+
|
|
207
|
+
self.normalize = normalize
|
|
208
|
+
self.use_raw = use_raw
|
|
209
|
+
self.target_sum = float(target_sum)
|
|
210
|
+
self.verbose = verbose
|
|
211
|
+
|
|
212
|
+
self.model = None
|
|
213
|
+
self.features: list[str] | None = None
|
|
214
|
+
self.missing_features: list[str] = []
|
|
215
|
+
|
|
216
|
+
def load(self) -> 'malignancy_inference':
|
|
217
|
+
"""
|
|
218
|
+
Load the pretrained model and the ordered feature list.
|
|
219
|
+
"""
|
|
220
|
+
|
|
221
|
+
model_path, feature_path = _resolve_pretrain_files(
|
|
222
|
+
self.pretrain_dir, self.model_path, self.feature_path,
|
|
223
|
+
)
|
|
224
|
+
|
|
225
|
+
self.model_path = model_path
|
|
226
|
+
self.feature_path = feature_path
|
|
227
|
+
|
|
228
|
+
if not os.path.isfile(model_path):
|
|
229
|
+
error(f'pretrained model not found: {model_path}')
|
|
230
|
+
|
|
231
|
+
try:
|
|
232
|
+
self.model = joblib.load(model_path)
|
|
233
|
+
except ImportError as e:
|
|
234
|
+
error(
|
|
235
|
+
'failed to load the pretrained model. the model may depend on a '
|
|
236
|
+
'package that is not installed (for example `xgboost`).',
|
|
237
|
+
error = e,
|
|
238
|
+
)
|
|
239
|
+
|
|
240
|
+
if not hasattr(self.model, 'predict_proba'):
|
|
241
|
+
error('the loaded model does not provide `predict_proba`.')
|
|
242
|
+
|
|
243
|
+
self.features = load_ordered_features(feature_path)
|
|
244
|
+
|
|
245
|
+
n_expected = getattr(self.model, 'n_features_in_', None)
|
|
246
|
+
if n_expected is not None and int(n_expected) != len(self.features):
|
|
247
|
+
warning(
|
|
248
|
+
f'the model expects {int(n_expected)} features, but the feature '
|
|
249
|
+
f'list contains {len(self.features)} entries.'
|
|
250
|
+
)
|
|
251
|
+
|
|
252
|
+
if self.verbose:
|
|
253
|
+
info(
|
|
254
|
+
'loaded pretrained malignancy model '
|
|
255
|
+
f'({type(self.model).__name__}, {len(self.features)} features).'
|
|
256
|
+
)
|
|
257
|
+
|
|
258
|
+
return self
|
|
259
|
+
|
|
260
|
+
def predict(
|
|
261
|
+
self,
|
|
262
|
+
adata: AnnData,
|
|
263
|
+
layer: str | None = None,
|
|
264
|
+
copy: bool = False,
|
|
265
|
+
key_prediction: str = 'malig',
|
|
266
|
+
key_probability: str = 'prob.malig',
|
|
267
|
+
) -> AnnData:
|
|
268
|
+
"""
|
|
269
|
+
Predict malignancy for each observation.
|
|
270
|
+
|
|
271
|
+
Parameters
|
|
272
|
+
----------
|
|
273
|
+
adata
|
|
274
|
+
Annotated data matrix with genes as variables and cells as
|
|
275
|
+
observations.
|
|
276
|
+
layer
|
|
277
|
+
Use ``adata.layers[layer]`` as the expression matrix. Cannot be
|
|
278
|
+
combined with ``use_raw = True``.
|
|
279
|
+
copy
|
|
280
|
+
Return a copy instead of writing to ``adata`` in place.
|
|
281
|
+
key_prediction
|
|
282
|
+
``adata.obs`` key for the predicted label, either ``Normal`` or
|
|
283
|
+
``Malignant``. Default ``'malig'``.
|
|
284
|
+
key_probability
|
|
285
|
+
``adata.obs`` key for the probability of being malignant.
|
|
286
|
+
Default ``'prob.malig'``.
|
|
287
|
+
|
|
288
|
+
Returns
|
|
289
|
+
-------
|
|
290
|
+
The ``AnnData`` object with predictions added to ``.obs``.
|
|
291
|
+
"""
|
|
292
|
+
|
|
293
|
+
if not isinstance(adata, AnnData):
|
|
294
|
+
error(f'`adata` must be an AnnData object, got {type(adata).__name__}.')
|
|
295
|
+
|
|
296
|
+
if self.model is None or self.features is None:
|
|
297
|
+
self.load()
|
|
298
|
+
|
|
299
|
+
X, var_names = _expression_matrix(
|
|
300
|
+
adata, use_raw = self.use_raw, layer = layer,
|
|
301
|
+
)
|
|
302
|
+
|
|
303
|
+
n_features = len(self.features)
|
|
304
|
+
cols, idx, missing = _feature_positions(self.features, var_names)
|
|
305
|
+
self.missing_features = missing
|
|
306
|
+
|
|
307
|
+
if self.verbose and len(missing) > 0:
|
|
308
|
+
pct = 100.0 * len(missing) / n_features
|
|
309
|
+
warning(
|
|
310
|
+
f'{len(missing)} of {n_features} model features ({pct:.2f}%) are '
|
|
311
|
+
'absent from the data and are imputed as zero.'
|
|
312
|
+
)
|
|
313
|
+
if pct > 20:
|
|
314
|
+
warning(
|
|
315
|
+
'more than 20% of the model features are missing. '
|
|
316
|
+
'prediction quality may be compromised.'
|
|
317
|
+
)
|
|
318
|
+
|
|
319
|
+
# build the feature matrix in the exact order expected by the model.
|
|
320
|
+
if len(idx) > 0:
|
|
321
|
+
sub = X[:, idx]
|
|
322
|
+
if sp.issparse(sub): sub = sub.toarray()
|
|
323
|
+
sub = np.asarray(sub)
|
|
324
|
+
dtype = np.result_type(sub.dtype, np.float32)
|
|
325
|
+
else:
|
|
326
|
+
sub = None
|
|
327
|
+
dtype = np.float64
|
|
328
|
+
|
|
329
|
+
dense = np.zeros((adata.n_obs, n_features), dtype = dtype)
|
|
330
|
+
if sub is not None:
|
|
331
|
+
dense[:, cols] = sub
|
|
332
|
+
del sub
|
|
333
|
+
|
|
334
|
+
# per-cell library size normalization. because the scaling factor is
|
|
335
|
+
# constant per cell it is equivalent to normalizing the full matrix
|
|
336
|
+
# first, but much cheaper.
|
|
337
|
+
if self.normalize:
|
|
338
|
+
totals = np.asarray(X.sum(axis = 1)).ravel()
|
|
339
|
+
scale = np.zeros(totals.shape, dtype = np.float64)
|
|
340
|
+
np.divide(self.target_sum, totals, out = scale, where = totals > 0)
|
|
341
|
+
dense *= scale[:, None]
|
|
342
|
+
|
|
343
|
+
proba = np.asarray(self.model.predict_proba(dense))
|
|
344
|
+
column = self._positive_index()
|
|
345
|
+
|
|
346
|
+
probability = proba.ravel() if proba.ndim == 1 else proba[:, column]
|
|
347
|
+
labels = np.asarray(self.model.predict(dense)).ravel()
|
|
348
|
+
|
|
349
|
+
classes = list(getattr(self.model, 'classes_', [0, 1]))
|
|
350
|
+
positive = classes[column] if column < len(classes) else 1
|
|
351
|
+
malignant = labels == positive
|
|
352
|
+
|
|
353
|
+
out = adata.copy() if copy else adata
|
|
354
|
+
out.obs[key_prediction] = pd.Categorical(
|
|
355
|
+
np.where(malignant, MALIGNANT, NORMAL),
|
|
356
|
+
categories = [NORMAL, MALIGNANT],
|
|
357
|
+
)
|
|
358
|
+
out.obs[key_probability] = probability.astype(np.float64)
|
|
359
|
+
|
|
360
|
+
return out
|
|
361
|
+
|
|
362
|
+
def _positive_index(self) -> int:
|
|
363
|
+
"""
|
|
364
|
+
Column of ``predict_proba`` corresponding to the malignant class (label 1).
|
|
365
|
+
"""
|
|
366
|
+
|
|
367
|
+
classes = list(getattr(self.model, 'classes_', [0, 1]))
|
|
368
|
+
if 1 in classes: return classes.index(1)
|
|
369
|
+
return len(classes) - 1
|
|
370
|
+
|
|
371
|
+
|
|
372
|
+
def predict_malignancy(
|
|
373
|
+
adata: AnnData,
|
|
374
|
+
pretrain_dir: str | None = None,
|
|
375
|
+
model_path: str | None = None,
|
|
376
|
+
feature_path: str | None = None,
|
|
377
|
+
normalize: bool = True,
|
|
378
|
+
use_raw: bool = False,
|
|
379
|
+
layer: str | None = None,
|
|
380
|
+
target_sum: float = DEFAULT_TARGET_SUM,
|
|
381
|
+
copy: bool = False,
|
|
382
|
+
key_prediction: str = 'malig',
|
|
383
|
+
key_probability: str = 'prob.malig',
|
|
384
|
+
verbose: bool = True,
|
|
385
|
+
) -> AnnData:
|
|
386
|
+
"""
|
|
387
|
+
Predict cell-level malignancy with a pretrained `scMalignantFinder` model.
|
|
388
|
+
|
|
389
|
+
This is a convenience wrapper around :class:`malignancy_inference`. Use the
|
|
390
|
+
class directly if you want to reuse the loaded model for several datasets.
|
|
391
|
+
|
|
392
|
+
Parameters
|
|
393
|
+
----------
|
|
394
|
+
adata
|
|
395
|
+
Annotated data matrix with genes as variables and cells as observations.
|
|
396
|
+
pretrain_dir
|
|
397
|
+
Directory containing ``model.joblib`` and ``ordered_feature.tsv``.
|
|
398
|
+
model_path
|
|
399
|
+
Explicit path to a pretrained ``model.joblib``.
|
|
400
|
+
feature_path
|
|
401
|
+
Explicit path to the ordered feature list.
|
|
402
|
+
normalize
|
|
403
|
+
Apply library size normalization to ``target_sum`` before prediction.
|
|
404
|
+
use_raw
|
|
405
|
+
Use ``adata.raw.X`` instead of ``adata.X``.
|
|
406
|
+
layer
|
|
407
|
+
Use ``adata.layers[layer]`` instead of ``adata.X``.
|
|
408
|
+
target_sum
|
|
409
|
+
Target total count per cell when ``normalize = True``.
|
|
410
|
+
copy
|
|
411
|
+
Return a copy instead of writing to ``adata`` in place.
|
|
412
|
+
key_prediction
|
|
413
|
+
``adata.obs`` key for the predicted label. Default ``'malig'``.
|
|
414
|
+
key_probability
|
|
415
|
+
``adata.obs`` key for the malignancy probability. Default ``'prob.malig'``.
|
|
416
|
+
verbose
|
|
417
|
+
Print information about the loaded model and missing features.
|
|
418
|
+
|
|
419
|
+
Returns
|
|
420
|
+
-------
|
|
421
|
+
The ``AnnData`` object with predictions added to ``.obs``.
|
|
422
|
+
"""
|
|
423
|
+
|
|
424
|
+
model = malignancy_inference(
|
|
425
|
+
pretrain_dir = pretrain_dir,
|
|
426
|
+
model_path = model_path,
|
|
427
|
+
feature_path = feature_path,
|
|
428
|
+
normalize = normalize,
|
|
429
|
+
use_raw = use_raw,
|
|
430
|
+
target_sum = target_sum,
|
|
431
|
+
verbose = verbose,
|
|
432
|
+
)
|
|
433
|
+
|
|
434
|
+
model.load()
|
|
435
|
+
return model.predict(
|
|
436
|
+
adata, layer = layer, copy = copy,
|
|
437
|
+
key_prediction = key_prediction,
|
|
438
|
+
key_probability = key_probability,
|
|
439
|
+
)
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
"""
|
|
2
|
+
gene set scoring utilities for malignant signatures.
|
|
3
|
+
|
|
4
|
+
The upstream `scMalignantFinder` implements its AUCell helper on top of
|
|
5
|
+
`pyscenic.aucell` and `ctxcore.genesig.GeneSignature`. This module uses the
|
|
6
|
+
in-package AUCell implementation (:mod:`exprmat.descriptive.aucell`) and the
|
|
7
|
+
in-package signature type (:class:`exprmat.data.signature.signature`) instead,
|
|
8
|
+
so neither `pyscenic` nor `ctxcore` is required.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import numpy as np
|
|
12
|
+
from anndata import AnnData
|
|
13
|
+
|
|
14
|
+
from exprmat.ansi import error, warning
|
|
15
|
+
from exprmat.data.signature import signature
|
|
16
|
+
from exprmat.descriptive.aucell import aucell, derive_auc_threshold
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def aucell_score(
|
|
20
|
+
adata: AnnData,
|
|
21
|
+
gmt: str,
|
|
22
|
+
layer: str | None = None,
|
|
23
|
+
normalize_total: bool = False,
|
|
24
|
+
target_sum: float = 1e4,
|
|
25
|
+
adapt_signatures: bool = True,
|
|
26
|
+
min_overlap: float = 0.5,
|
|
27
|
+
auc_threshold: float | None = None,
|
|
28
|
+
seed: int | None = 2,
|
|
29
|
+
num_workers: int = 1,
|
|
30
|
+
key_added: str | None = None,
|
|
31
|
+
copy: bool = False,
|
|
32
|
+
) -> AnnData:
|
|
33
|
+
"""
|
|
34
|
+
Calculate per-observation AUCell scores for the gene sets in a gmt file.
|
|
35
|
+
|
|
36
|
+
This mirrors ``scMalignantFinder.utils.aucell_cal`` but is backed by the
|
|
37
|
+
in-package AUCell implementation. Scores are normalized to a maximum of 1.0
|
|
38
|
+
per gene set, as upstream.
|
|
39
|
+
|
|
40
|
+
.. note::
|
|
41
|
+
The expression matrix is densified internally, so this helper is intended
|
|
42
|
+
for a biologically relevant subset of cells.
|
|
43
|
+
|
|
44
|
+
Parameters
|
|
45
|
+
----------
|
|
46
|
+
adata
|
|
47
|
+
Annotated data matrix with genes as variables and cells as observations.
|
|
48
|
+
gmt
|
|
49
|
+
Path to a gene set file in gmt format.
|
|
50
|
+
layer
|
|
51
|
+
Use ``adata.layers[layer]`` as the expression matrix. Defaults to
|
|
52
|
+
``adata.X``.
|
|
53
|
+
normalize_total
|
|
54
|
+
Normalize total counts to ``target_sum`` per cell before scoring. The
|
|
55
|
+
input ``adata`` is not modified.
|
|
56
|
+
target_sum
|
|
57
|
+
Target total count per cell when ``normalize_total = True``.
|
|
58
|
+
adapt_signatures
|
|
59
|
+
Drop gene sets whose overlap with the variables of the data is below
|
|
60
|
+
``min_overlap``. Without this, sets composed mostly of absent genes
|
|
61
|
+
would be scored as (near) zero.
|
|
62
|
+
min_overlap
|
|
63
|
+
Minimum fraction of genes of a set that must be present in the data.
|
|
64
|
+
auc_threshold
|
|
65
|
+
Fraction of the ranked genome to use for the AUC. Defaults to the 1%
|
|
66
|
+
quantile of detected genes, as derived by
|
|
67
|
+
:func:`exprmat.descriptive.aucell.derive_auc_threshold`.
|
|
68
|
+
seed
|
|
69
|
+
Seed used when shuffling the expression matrix before ranking.
|
|
70
|
+
num_workers
|
|
71
|
+
Number of worker processes used for the AUC computation.
|
|
72
|
+
key_added
|
|
73
|
+
If ``None`` (default), one column per gene set is added to ``adata.obs``.
|
|
74
|
+
Otherwise, scores are stored in ``adata.obsm[key_added]`` and the gene
|
|
75
|
+
set names in ``adata.uns['{key_added}.genesets']``.
|
|
76
|
+
copy
|
|
77
|
+
Return a copy instead of writing to ``adata`` in place.
|
|
78
|
+
|
|
79
|
+
Returns
|
|
80
|
+
-------
|
|
81
|
+
The ``AnnData`` object with the scores added.
|
|
82
|
+
"""
|
|
83
|
+
|
|
84
|
+
if not isinstance(adata, AnnData):
|
|
85
|
+
error(f'`adata` must be an AnnData object, got {type(adata).__name__}.')
|
|
86
|
+
|
|
87
|
+
if not isinstance(gmt, str):
|
|
88
|
+
error('`gmt` must be a path to a gmt file.')
|
|
89
|
+
|
|
90
|
+
signatures = signature.from_gmt(
|
|
91
|
+
gmt, field_separator = '\t', gene_separator = '\t',
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
gene_names = set(map(str, adata.var_names))
|
|
95
|
+
|
|
96
|
+
if adapt_signatures:
|
|
97
|
+
kept = []
|
|
98
|
+
for s in signatures:
|
|
99
|
+
overlap = len(set(map(str, s.gene2weight)) & gene_names) / len(s)
|
|
100
|
+
if overlap >= min_overlap: kept.append(s)
|
|
101
|
+
|
|
102
|
+
if len(kept) == 0:
|
|
103
|
+
error(
|
|
104
|
+
f'none of the {len(signatures)} gene sets in `{gmt}` overlap with '
|
|
105
|
+
f'at least {min_overlap:.0%} of the variables of the data.'
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
if len(kept) < len(signatures):
|
|
109
|
+
warning(
|
|
110
|
+
f'{len(signatures) - len(kept)} of {len(signatures)} gene sets '
|
|
111
|
+
f'were dropped (< {min_overlap:.0%} overlap with the data).'
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
signatures = kept
|
|
115
|
+
|
|
116
|
+
if len(signatures) == 0:
|
|
117
|
+
error(f'no usable gene sets found in `{gmt}`.')
|
|
118
|
+
|
|
119
|
+
names = [str(s.name) for s in signatures]
|
|
120
|
+
if len(set(names)) != len(names):
|
|
121
|
+
warning('duplicated gene set names in the gmt file; scores will collide.')
|
|
122
|
+
|
|
123
|
+
# the expression matrix as a dense (cell x gene) dataframe, which is what
|
|
124
|
+
# the ranking based AUCell implementation expects.
|
|
125
|
+
df = adata.to_df(layer = layer)
|
|
126
|
+
|
|
127
|
+
if normalize_total:
|
|
128
|
+
totals = df.sum(axis = 1).to_numpy(dtype = np.float64)
|
|
129
|
+
scale = np.zeros(totals.shape, dtype = np.float64)
|
|
130
|
+
np.divide(float(target_sum), totals, out = scale, where = totals > 0)
|
|
131
|
+
df = df.mul(scale, axis = 0)
|
|
132
|
+
|
|
133
|
+
if auc_threshold is None:
|
|
134
|
+
auc_threshold = float(derive_auc_threshold(df)[0.01])
|
|
135
|
+
|
|
136
|
+
scores = aucell(
|
|
137
|
+
df, signatures,
|
|
138
|
+
auc_threshold = auc_threshold,
|
|
139
|
+
normalize = True,
|
|
140
|
+
seed = seed,
|
|
141
|
+
num_workers = num_workers,
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
# keep the original observation order.
|
|
145
|
+
scores = scores.reindex(adata.obs_names)
|
|
146
|
+
|
|
147
|
+
out = adata.copy() if copy else adata
|
|
148
|
+
|
|
149
|
+
if key_added is None:
|
|
150
|
+
for i, name in enumerate(scores.columns):
|
|
151
|
+
out.obs[str(name)] = scores.iloc[:, i].to_numpy()
|
|
152
|
+
else:
|
|
153
|
+
out.obsm[key_added] = scores.to_numpy()
|
|
154
|
+
out.uns[f'{key_added}.genesets'] = list(map(str, scores.columns))
|
|
155
|
+
|
|
156
|
+
return out
|