exprmat 0.1.48__tar.gz → 0.1.50__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.48 → exprmat-0.1.50}/PKG-INFO +5 -5
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/__init__.py +29 -1
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/clustering/gating.py +1 -0
- exprmat-0.1.50/exprmat/data/icnet.py +74 -0
- exprmat-0.1.50/exprmat/lr/icnet/__init__.py +100 -0
- exprmat-0.1.50/exprmat/lr/icnet/construction.py +270 -0
- exprmat-0.1.50/exprmat/lr/icnet/importance.py +159 -0
- exprmat-0.1.50/exprmat/lr/icnet/ligand.py +333 -0
- exprmat-0.1.50/exprmat/lr/icnet/metrics.py +90 -0
- exprmat-0.1.50/exprmat/lr/icnet/pagerank.py +124 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/plotting/expression.py +4 -4
- exprmat-0.1.50/exprmat/plotting/icnet.py +28 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/plotting/utils.py +2 -2
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/plotting/velocity.py +2 -1
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/reader/experiment.py +29 -31
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/reader/matcher.py +2 -2
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/reader/spatial.py +4 -4
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/reader/static.py +20 -2
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/reduction/plot.py +1 -1
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/utils.py +4 -0
- exprmat-0.1.50/license +674 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/pyproject.toml +2 -2
- {exprmat-0.1.48 → exprmat-0.1.50}/readme.md +3 -3
- exprmat-0.1.48/license +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/Cargo.lock +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/Cargo.toml +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/ansi.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/clustering/__init__.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/clustering/cnmf.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/clustering/dbscan.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/clustering/kmeans.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/clustering/leiden.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/clustering/nmf.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/clustering/rogue.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/clustering/sc3.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/clustering/seriation.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/clustering/spectral.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/clustering/utils.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/cnv/__init__.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/cnv/cnvscore.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/cnv/infercnv.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/configuration.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/data/__init__.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/data/cistarget.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/data/cre.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/data/finders.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/data/geneset.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/data/io.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/data/lr.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/data/orthologs.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/data/presets.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/data/signature.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/data/tf.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/deconv/__init__.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/deconv/deconv.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/deconv/simulation.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/descriptive/__init__.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/descriptive/aggregate.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/descriptive/atac.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/descriptive/aucell.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/descriptive/de.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/descriptive/gse.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/descriptive/kde.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/descriptive/recovery.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/descriptive/summary.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/descriptive/tcr.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/deseq/dataset.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/deseq/gridsearch.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/deseq/inference.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/deseq/preprocessing.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/deseq/stats.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/deseq/utils.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/dynamics/__init__.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/dynamics/generank.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/dynamics/linreg.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/dynamics/moments.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/dynamics/optimization.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/dynamics/parallel.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/dynamics/preprocess.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/dynamics/pseudotime.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/dynamics/transition.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/dynamics/utils.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/dynamics/velocity.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/grn/__init__.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/grn/infergrn.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/grn/modules.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/grn/prune.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/grn/regressors.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/grn/utils.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/image/__init__.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/image/align.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/lr/__init__.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/lr/aggregate.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/lr/method.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/lr/methods/__init__.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/lr/methods/cellchat.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/lr/methods/cellphonedb.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/lr/methods/connectome.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/lr/methods/geomean.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/lr/methods/logfc.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/lr/methods/natmi.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/lr/methods/rank_aggregate.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/lr/methods/scseqcomm.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/lr/methods/singlecellsignalr.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/lr/pipeline.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/lr/preprocess.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/lr/resources.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/lr/utils.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/metacell/__init__.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/metacell/engine.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/metacell/model.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/metacell/utils.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/peaks/__init__.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/peaks/callpeak.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/peaks/common.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/peaks/coverage.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/peaks/footprint.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/peaks/idr/__init__.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/peaks/idr/constants.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/peaks/idr/idr.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/peaks/idr/invcdf.pyx +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/peaks/idr/optimization.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/peaks/idr/utils.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/peaks/linkage.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/peaks/motif.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/peaks/sequence.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/plotting/__init__.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/plotting/atac.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/plotting/cnmf.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/plotting/cnv.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/plotting/data/A.pk +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/plotting/data/B.pk +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/plotting/data/C.pk +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/plotting/data/D.pk +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/plotting/data/E.pk +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/plotting/data/F.pk +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/plotting/data/G.pk +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/plotting/data/H.pk +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/plotting/data/I.pk +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/plotting/data/J.pk +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/plotting/data/K.pk +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/plotting/data/L.pk +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/plotting/data/M.pk +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/plotting/data/N.pk +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/plotting/data/O.pk +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/plotting/data/P.pk +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/plotting/data/Q.pk +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/plotting/data/R.pk +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/plotting/data/S.pk +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/plotting/data/T.pk +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/plotting/data/U.pk +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/plotting/data/V.pk +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/plotting/data/W.pk +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/plotting/data/X.pk +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/plotting/data/Y.pk +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/plotting/data/Z.pk +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/plotting/de.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/plotting/gse.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/plotting/lr.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/plotting/milestone.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/plotting/palettes.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/plotting/sankey.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/plotting/sequence.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/plotting/summary.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/plotting/track.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/plotting/trajectory.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/preprocessing/__init__.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/preprocessing/doublets/__init__.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/preprocessing/doublets/composite.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/preprocessing/doublets/scrublet.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/preprocessing/emptydrops.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/preprocessing/filter.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/preprocessing/impute/__init__.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/preprocessing/impute/magic.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/preprocessing/integrate.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/preprocessing/linear.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/preprocessing/normal.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/preprocessing/plot.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/preprocessing/qc.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/preprocessing/sctransform/__init__.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/preprocessing/sctransform/estimate.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/preprocessing/sctransform/ksmooth.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/preprocessing/sctransform/residual.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/preprocessing/sctransform/transform.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/preprocessing/sparse.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/preprocessing/uniform.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/reader/__init__.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/reader/conversions.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/reader/metadata.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/reader/updater.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/reduction/__init__.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/reduction/diffmap.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/reduction/forceatlas.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/reduction/mde.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/reduction/nn.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/reduction/outliers.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/reduction/pca.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/reduction/scvi.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/reduction/spectral.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/reduction/tsne.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/reduction/umap.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/trajectory/__init__.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/trajectory/cytotrace.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/trajectory/elpi.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/trajectory/pcurve.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/trajectory/pseudotime.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/trajectory/root.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/trajectory/trace.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/transfer/__init__.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/exprmat/transfer/atlas.py +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/snapatac2/Cargo.toml +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/snapatac2/license +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/snapatac2/readme +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/snapatac2/src/call_peaks.rs +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/snapatac2/src/embedding.rs +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/snapatac2/src/export.rs +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/snapatac2/src/knn.rs +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/snapatac2/src/lib.rs +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/snapatac2/src/motif.rs +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/snapatac2/src/network.rs +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/snapatac2/src/preprocessing.rs +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/snapatac2/src/utils/anndata.rs +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/snapatac2/src/utils.rs +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/snapatac2-core/Cargo.toml +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/snapatac2-core/src/embedding.rs +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/snapatac2-core/src/export.rs +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/snapatac2-core/src/feature_count/counter.rs +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/snapatac2-core/src/feature_count/data_iter.rs +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/snapatac2-core/src/feature_count/matrix.rs +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/snapatac2-core/src/feature_count/mod.rs +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/snapatac2-core/src/genome.rs +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/snapatac2-core/src/lib.rs +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/snapatac2-core/src/motif.rs +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/snapatac2-core/src/network.rs +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/snapatac2-core/src/preprocessing/bam/flagstat.rs +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/snapatac2-core/src/preprocessing/bam/header.rs +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/snapatac2-core/src/preprocessing/bam/mark_duplicates.rs +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/snapatac2-core/src/preprocessing/bam.rs +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/snapatac2-core/src/preprocessing/import.rs +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/snapatac2-core/src/preprocessing/mod.rs +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/snapatac2-core/src/preprocessing/qc.rs +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/snapatac2-core/src/utils/knn.rs +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/snapatac2-core/src/utils/mod.rs +0 -0
- {exprmat-0.1.48 → exprmat-0.1.50}/snapatac2-core/src/utils/similarity.rs +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: exprmat
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.50
|
|
4
4
|
Classifier: Programming Language :: Rust
|
|
5
5
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
6
6
|
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
@@ -101,7 +101,7 @@ Provides-Extra: cuda12
|
|
|
101
101
|
License-File: license
|
|
102
102
|
Summary: exprmat: Routines for expression matrices
|
|
103
103
|
Author-email: Zheng Yang <xornent@outlook.com>
|
|
104
|
-
Requires-Python: >=3.
|
|
104
|
+
Requires-Python: >=3.10, <3.13
|
|
105
105
|
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
|
|
106
106
|
Project-URL: Repository, https://github.com/yang-z-03/exprmat
|
|
107
107
|
|
|
@@ -150,18 +150,18 @@ options:
|
|
|
150
150
|
--version VERSION The version to fetch from remote.
|
|
151
151
|
```
|
|
152
152
|
|
|
153
|
-
Suppose you are installing the database version `0.1.
|
|
153
|
+
Suppose you are installing the database version `0.1.50` to `~/database`.
|
|
154
154
|
|
|
155
155
|
```bash
|
|
156
156
|
# enter the intended path of installation
|
|
157
157
|
cd ~/database
|
|
158
158
|
|
|
159
|
-
# download the version 0.1.
|
|
159
|
+
# download the version 0.1.50 of database distribution
|
|
160
160
|
# you must download the same version of the database with the package. the database
|
|
161
161
|
# and package content are published strictly synchronically.
|
|
162
162
|
bsync-fetch --id <your-id> --secret <your-api-secret> \
|
|
163
163
|
--bucket exprmat-data --endpoint oss-cn-wuhan-lr.aliyuncs.com \
|
|
164
|
-
--version 0.1.
|
|
164
|
+
--version 0.1.50
|
|
165
165
|
```
|
|
166
166
|
|
|
167
167
|
The authentication tokens passed to `--id` and `--secret` is provided by the
|
|
@@ -82,7 +82,7 @@ due to the extensive size of the reference data. You need to setup the database
|
|
|
82
82
|
and configure it properly with configuration file `.exprmatrc` under your
|
|
83
83
|
user root or current working directory
|
|
84
84
|
|
|
85
|
-
For more guide on how to
|
|
85
|
+
For more guide on how to install the database, and more information about
|
|
86
86
|
what the database includes, see <https://github.com/yang-z-03/exprmat>
|
|
87
87
|
"""
|
|
88
88
|
|
|
@@ -192,6 +192,22 @@ def memory():
|
|
|
192
192
|
info(f'virtual memory: {format_file_size(virtual)}')
|
|
193
193
|
|
|
194
194
|
|
|
195
|
+
def license():
|
|
196
|
+
print(f'''
|
|
197
|
+
exprmat {ver_string} - Routines to manipulate expression matrices
|
|
198
|
+
Copyright (C) 2025 - 2026 Zheng Yang (杨政) <xornent@outlook.com>
|
|
199
|
+
|
|
200
|
+
exprmat is free software and comes with ABSOLUTELY NO WARRANTY.
|
|
201
|
+
You are welcome to redistribute it under certain conditions.
|
|
202
|
+
You should have received a copy of the GNU General Public License
|
|
203
|
+
version 3 along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
204
|
+
|
|
205
|
+
The GNU General Public License does not permit incorporating
|
|
206
|
+
your program into proprietary programs.
|
|
207
|
+
''')
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
|
|
195
211
|
setwd = os.chdir
|
|
196
212
|
getwd = os.getcwd
|
|
197
213
|
|
|
@@ -200,6 +216,17 @@ import tqdm
|
|
|
200
216
|
tqdm.tqdm(disable = True, total = 0)
|
|
201
217
|
|
|
202
218
|
|
|
219
|
+
# show version info after any install or update of the database.
|
|
220
|
+
# this always synchronizes with the package update.
|
|
221
|
+
|
|
222
|
+
try:
|
|
223
|
+
fd = os.open(os.path.join(basepath, '.license'), os.O_CREAT | os.O_EXCL | os.O_WRONLY)
|
|
224
|
+
with os.fdopen(fd, "w") as f: f.write("shown")
|
|
225
|
+
license()
|
|
226
|
+
|
|
227
|
+
except FileExistsError: pass
|
|
228
|
+
|
|
229
|
+
|
|
203
230
|
__all__ = [
|
|
204
231
|
# exposed external namespace
|
|
205
232
|
'np', 'mu', 'ad', 'sc', 'pd',
|
|
@@ -219,6 +246,7 @@ __all__ = [
|
|
|
219
246
|
'version_db'
|
|
220
247
|
'cuda',
|
|
221
248
|
'memory',
|
|
249
|
+
'license',
|
|
222
250
|
'setwd',
|
|
223
251
|
'getwd',
|
|
224
252
|
'pprog',
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
|
|
2
|
+
from exprmat import basepath
|
|
3
|
+
import pandas as pd
|
|
4
|
+
import os
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def get_gene_regulatory_network(taxa):
|
|
8
|
+
return pd.read_feather(os.path.join(basepath, taxa, 'icnet', 'gene-regulatory.feather'))
|
|
9
|
+
|
|
10
|
+
def get_lr_network(taxa):
|
|
11
|
+
return pd.read_feather(os.path.join(basepath, taxa, 'icnet', 'ligand-receptors.feather'))
|
|
12
|
+
|
|
13
|
+
def get_signaling_network(taxa):
|
|
14
|
+
return pd.read_feather(os.path.join(basepath, taxa, 'icnet', 'signaling.feather'))
|
|
15
|
+
|
|
16
|
+
def get_gene_regulatory_weights(taxa, version = 'v2'):
|
|
17
|
+
return pd.read_feather(os.path.join(basepath, taxa, 'icnet', version, 'gene-regulatory.feather'))
|
|
18
|
+
|
|
19
|
+
def get_lr_weights(taxa, version = 'v2'):
|
|
20
|
+
return pd.read_feather(os.path.join(basepath, taxa, 'icnet', version, 'lr-significance.feather'))
|
|
21
|
+
|
|
22
|
+
def get_ligand_target_matrix(taxa, version = 'v2'):
|
|
23
|
+
return pd.read_feather(os.path.join(basepath, taxa, 'icnet', version, 'ligand-target.feather'))
|
|
24
|
+
|
|
25
|
+
def get_ligand_tf_matrix(taxa, version = 'v2'):
|
|
26
|
+
return pd.read_feather(os.path.join(basepath, taxa, 'icnet', version, 'ligand-tf.feather'))
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def get_weighted_ligand_target_links(ligand, geneset, ligand_target_matrix, n = 250):
|
|
30
|
+
import numpy as np
|
|
31
|
+
ltm_series = ligand_target_matrix[ligand]
|
|
32
|
+
data = np.array(ltm_series.values)
|
|
33
|
+
flat = data.flatten('C')
|
|
34
|
+
indices = np.argsort(flat)[-n:]
|
|
35
|
+
|
|
36
|
+
# retrieve indices
|
|
37
|
+
# rows are targets and columns are ligands.
|
|
38
|
+
ligs = []
|
|
39
|
+
targs = []
|
|
40
|
+
weights = []
|
|
41
|
+
for i in indices:
|
|
42
|
+
row = i // len(ligand)
|
|
43
|
+
col = i % len(ligand)
|
|
44
|
+
target = ligand_target_matrix.index[row]
|
|
45
|
+
if target in geneset:
|
|
46
|
+
ligs.append(ligand[col])
|
|
47
|
+
targs.append(ligand_target_matrix.index[row])
|
|
48
|
+
weights.append(flat[i])
|
|
49
|
+
|
|
50
|
+
return pd.DataFrame({
|
|
51
|
+
'ligand': ligs,
|
|
52
|
+
'target': targs,
|
|
53
|
+
'weight': weights
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def get_weighted_ligand_receptor_links(
|
|
58
|
+
best_upstream_ligands, expressed_receptors,
|
|
59
|
+
lr_network, weighted_networks_lr_sig
|
|
60
|
+
):
|
|
61
|
+
lr_network = lr_network.drop_duplicates(subset = ['from', 'to'])
|
|
62
|
+
weighted_networks_lr = pd.merge(weighted_networks_lr_sig, lr_network, on = ['from', 'to'])
|
|
63
|
+
|
|
64
|
+
lr_network_top = lr_network[
|
|
65
|
+
(lr_network['from'].isin(best_upstream_ligands)) &
|
|
66
|
+
(lr_network['to'].isin(expressed_receptors))
|
|
67
|
+
].drop_duplicates(subset = ['from','to'])
|
|
68
|
+
best_upstream_receptors = lr_network_top['to'].unique()
|
|
69
|
+
|
|
70
|
+
lr_network_top_df_long = weighted_networks_lr[
|
|
71
|
+
(weighted_networks_lr['from'].isin(best_upstream_ligands)) &
|
|
72
|
+
(weighted_networks_lr['to'].isin(best_upstream_receptors))]
|
|
73
|
+
|
|
74
|
+
return lr_network_top_df_long
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
|
|
2
|
+
from exprmat.data.icnet import (
|
|
3
|
+
get_gene_regulatory_network,
|
|
4
|
+
get_gene_regulatory_weights,
|
|
5
|
+
get_ligand_target_matrix,
|
|
6
|
+
get_ligand_tf_matrix,
|
|
7
|
+
get_lr_network,
|
|
8
|
+
get_lr_weights,
|
|
9
|
+
get_signaling_network,
|
|
10
|
+
get_weighted_ligand_receptor_links,
|
|
11
|
+
get_weighted_ligand_target_links
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
from exprmat.lr.icnet.importance import predict_ligand_activities
|
|
15
|
+
from exprmat import info, error
|
|
16
|
+
import numpy as np
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def nichenet(
|
|
20
|
+
adata,
|
|
21
|
+
taxa,
|
|
22
|
+
receiver, # you must specify the receiver cells
|
|
23
|
+
sender = None,
|
|
24
|
+
identity = 'cell.type',
|
|
25
|
+
foreground = None,
|
|
26
|
+
background = None,
|
|
27
|
+
expression_threshold = 0.001,
|
|
28
|
+
ncpus = 1,
|
|
29
|
+
key_added = 'nichenet'
|
|
30
|
+
):
|
|
31
|
+
ltm = get_ligand_target_matrix(taxa)
|
|
32
|
+
|
|
33
|
+
if background:
|
|
34
|
+
background = list(set(background))
|
|
35
|
+
info(f'using user-specified background gene set of size {len(background)}')
|
|
36
|
+
|
|
37
|
+
else: background = adata.var['gene'].tolist()
|
|
38
|
+
background = list(set(background).intersection(set(ltm.index.tolist())))
|
|
39
|
+
info(f'background gene set constructed with size {len(background)}')
|
|
40
|
+
|
|
41
|
+
if foreground:
|
|
42
|
+
foreground = list(set(foreground))
|
|
43
|
+
info(f'using user-specified foreground gene set of size {len(foreground)}')
|
|
44
|
+
else: error('foreground gene set must be specified')
|
|
45
|
+
|
|
46
|
+
expressed_genes = adata.var['gene'].loc[
|
|
47
|
+
np.array((adata.X.sum(0) / adata.X.shape[0]) > expression_threshold)[0]].tolist()
|
|
48
|
+
rec = adata[[x in receiver for x in adata.obs[identity]], :]
|
|
49
|
+
target_expressed_genes = rec.var['gene'].loc[np.array(
|
|
50
|
+
(rec.X.sum(0) / rec.X.shape[0]) > expression_threshold)[0]].tolist()
|
|
51
|
+
|
|
52
|
+
lr_network = get_lr_network(taxa)
|
|
53
|
+
all_receptors = lr_network['to'].unique().tolist()
|
|
54
|
+
expressed_receptors = list(set(all_receptors).intersection(set(target_expressed_genes)))
|
|
55
|
+
potential_ligands = [x for x, y in zip(lr_network['from'], lr_network['to']) if y in expressed_genes]
|
|
56
|
+
|
|
57
|
+
if sender:
|
|
58
|
+
send = adata[[x in sender for x in adata.obs[identity]], :]
|
|
59
|
+
sender_expressed_genes = send.var['gene'].loc[np.array(
|
|
60
|
+
(send.X.sum(0) / send.X.shape[0]) > expression_threshold)[0]].tolist()
|
|
61
|
+
potential_ligands = list(set(potential_ligands).intersection(set(sender_expressed_genes)))
|
|
62
|
+
info(f'{len(potential_ligands)} potential ligands filtered by sender cells expression')
|
|
63
|
+
else:
|
|
64
|
+
potential_ligands = list(set(potential_ligands))
|
|
65
|
+
info(f'using {len(potential_ligands)}(all) potential ligands')
|
|
66
|
+
|
|
67
|
+
info(f'using {len(expressed_receptors)} expressed receptors in receivers')
|
|
68
|
+
|
|
69
|
+
ligact = predict_ligand_activities(
|
|
70
|
+
geneset = foreground,
|
|
71
|
+
background_expressed_genes = background,
|
|
72
|
+
ligand_target_matrix = ltm.values,
|
|
73
|
+
ligand_names = ltm.columns.tolist(),
|
|
74
|
+
target_names = ltm.index.tolist(),
|
|
75
|
+
potential_ligands = potential_ligands,
|
|
76
|
+
ncpus = ncpus
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
adata.uns[key_added] = {
|
|
80
|
+
'foreground': foreground,
|
|
81
|
+
'background': background,
|
|
82
|
+
'taxa': taxa,
|
|
83
|
+
'activities': ligact.sort_values(['aupr.adj'], ascending = False)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
pass
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def nichenet_infer_targets(adata, key_nichenet, ligands = 10, n_targets = 250):
|
|
90
|
+
|
|
91
|
+
nnet = adata.uns[key_nichenet]
|
|
92
|
+
ltm = get_ligand_target_matrix(nnet['taxa'])
|
|
93
|
+
ltl = get_weighted_ligand_target_links(
|
|
94
|
+
ligand = ligands if isinstance(ligands, list) else nnet['activities'].head(ligands)['ligand'].tolist(),
|
|
95
|
+
geneset = nnet['foreground'],
|
|
96
|
+
ligand_target_matrix = ltm,
|
|
97
|
+
n = n_targets
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
adata.uns[key_nichenet]['ligand_targets'] = ltl
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Network construction functions: weighted networks and hub corrections
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import pandas as pd
|
|
6
|
+
import numpy as np
|
|
7
|
+
from typing import Dict, List, Tuple, Optional
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def construct_weighted_networks(
|
|
11
|
+
lr_network: pd.DataFrame,
|
|
12
|
+
sig_network: pd.DataFrame,
|
|
13
|
+
gr_network: pd.DataFrame,
|
|
14
|
+
source_weights_df: pd.DataFrame,
|
|
15
|
+
n_output_networks: int = 2
|
|
16
|
+
) -> Dict[str, pd.DataFrame]:
|
|
17
|
+
"""
|
|
18
|
+
Construct layer-specific weighted integrated networks from input source networks
|
|
19
|
+
via weighted aggregation.
|
|
20
|
+
|
|
21
|
+
Parameters:
|
|
22
|
+
-----------
|
|
23
|
+
lr_network : pd.DataFrame
|
|
24
|
+
Ligand-receptor interactions (required columns: from, to, source)
|
|
25
|
+
sig_network : pd.DataFrame
|
|
26
|
+
Signaling interactions (required columns: from, to, source)
|
|
27
|
+
gr_network : pd.DataFrame
|
|
28
|
+
Gene regulatory interactions (required columns: from, to, source)
|
|
29
|
+
source_weights_df : pd.DataFrame
|
|
30
|
+
Weights associated to each data source (required columns: source, weight)
|
|
31
|
+
n_output_networks : int
|
|
32
|
+
Number of output networks: 2 (ligand-signaling and gene regulatory; default)
|
|
33
|
+
or 3 (ligand-receptor, signaling and gene regulatory)
|
|
34
|
+
|
|
35
|
+
Returns:
|
|
36
|
+
--------
|
|
37
|
+
dict
|
|
38
|
+
Dictionary containing:
|
|
39
|
+
- If n_output_networks=2: {'lr_sig': DataFrame, 'gr': DataFrame}
|
|
40
|
+
- If n_output_networks=3: {'lr': DataFrame, 'sig': DataFrame, 'gr': DataFrame}
|
|
41
|
+
Each DataFrame has columns: from, to, weight
|
|
42
|
+
"""
|
|
43
|
+
# Input validation
|
|
44
|
+
if not isinstance(lr_network, pd.DataFrame):
|
|
45
|
+
raise TypeError("lr_network must be a pandas DataFrame")
|
|
46
|
+
if not isinstance(sig_network, pd.DataFrame):
|
|
47
|
+
raise TypeError("sig_network must be a pandas DataFrame")
|
|
48
|
+
if not isinstance(gr_network, pd.DataFrame):
|
|
49
|
+
raise TypeError("gr_network must be a pandas DataFrame")
|
|
50
|
+
if not isinstance(source_weights_df, pd.DataFrame):
|
|
51
|
+
raise TypeError("source_weights_df must be a pandas DataFrame")
|
|
52
|
+
|
|
53
|
+
required_cols_lr = ['from', 'to', 'source']
|
|
54
|
+
required_cols_weights = ['source', 'weight']
|
|
55
|
+
|
|
56
|
+
for col in required_cols_lr:
|
|
57
|
+
if col not in lr_network.columns:
|
|
58
|
+
raise ValueError(f"lr_network must have column '{col}'")
|
|
59
|
+
if col not in sig_network.columns:
|
|
60
|
+
raise ValueError(f"sig_network must have column '{col}'")
|
|
61
|
+
if col not in gr_network.columns:
|
|
62
|
+
raise ValueError(f"gr_network must have column '{col}'")
|
|
63
|
+
|
|
64
|
+
for col in required_cols_weights:
|
|
65
|
+
if col not in source_weights_df.columns:
|
|
66
|
+
raise ValueError(f"source_weights_df must have column '{col}'")
|
|
67
|
+
|
|
68
|
+
if (source_weights_df['weight'] > 1).any():
|
|
69
|
+
raise ValueError("No data source weight may be higher than 1")
|
|
70
|
+
|
|
71
|
+
if n_output_networks not in [2, 3]:
|
|
72
|
+
raise ValueError("n_output_networks must be 2 or 3")
|
|
73
|
+
|
|
74
|
+
# Remove data sources for which weight equals 0
|
|
75
|
+
source_weights_df = source_weights_df[source_weights_df['weight'] > 0].copy()
|
|
76
|
+
|
|
77
|
+
# Perform weighted network aggregation for gene regulatory network
|
|
78
|
+
gr_network_w = (
|
|
79
|
+
gr_network
|
|
80
|
+
.merge(source_weights_df, on='source', how='inner')
|
|
81
|
+
.groupby(['from', 'to'], as_index=False)
|
|
82
|
+
.agg({'weight': 'sum'})
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
if n_output_networks == 2:
|
|
86
|
+
# Combine ligand-receptor and signaling networks
|
|
87
|
+
ligand_signaling_w = (
|
|
88
|
+
pd.concat([lr_network, sig_network], ignore_index=True)
|
|
89
|
+
.merge(source_weights_df, on='source', how='inner')
|
|
90
|
+
.groupby(['from', 'to'], as_index=False)
|
|
91
|
+
.agg({'weight': 'sum'})
|
|
92
|
+
)
|
|
93
|
+
return {
|
|
94
|
+
'lr_sig': ligand_signaling_w,
|
|
95
|
+
'gr': gr_network_w
|
|
96
|
+
}
|
|
97
|
+
else: # n_output_networks == 3
|
|
98
|
+
lr_network_w = (
|
|
99
|
+
lr_network
|
|
100
|
+
.merge(source_weights_df, on='source', how='inner')
|
|
101
|
+
.groupby(['from', 'to'], as_index=False)
|
|
102
|
+
.agg({'weight': 'sum'})
|
|
103
|
+
)
|
|
104
|
+
sig_network_w = (
|
|
105
|
+
sig_network
|
|
106
|
+
.merge(source_weights_df, on='source', how='inner')
|
|
107
|
+
.groupby(['from', 'to'], as_index=False)
|
|
108
|
+
.agg({'weight': 'sum'})
|
|
109
|
+
)
|
|
110
|
+
return {
|
|
111
|
+
'lr': lr_network_w,
|
|
112
|
+
'sig': sig_network_w,
|
|
113
|
+
'gr': gr_network_w
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def apply_hub_corrections(
|
|
118
|
+
weighted_networks: Dict[str, pd.DataFrame],
|
|
119
|
+
lr_sig_hub: float,
|
|
120
|
+
gr_hub: float
|
|
121
|
+
) -> Dict[str, pd.DataFrame]:
|
|
122
|
+
"""
|
|
123
|
+
Apply hub corrections to the weighted integrated ligand-signaling and gene
|
|
124
|
+
regulatory network. Downweighs the importance of nodes with a lot of incoming links.
|
|
125
|
+
|
|
126
|
+
Hub correction method: W_cor = W * D^(-h)
|
|
127
|
+
where D is the indegree matrix and h is the correction factor.
|
|
128
|
+
|
|
129
|
+
Parameters:
|
|
130
|
+
-----------
|
|
131
|
+
weighted_networks : dict
|
|
132
|
+
Dictionary with keys 'lr_sig' and 'gr', each containing a DataFrame
|
|
133
|
+
with columns: from, to, weight
|
|
134
|
+
lr_sig_hub : float
|
|
135
|
+
Hub correction factor for ligand-signaling network (0-1).
|
|
136
|
+
0: no correction, 1: maximal correction
|
|
137
|
+
gr_hub : float
|
|
138
|
+
Hub correction factor for gene regulatory network (0-1).
|
|
139
|
+
0: no correction, 1: maximal correction
|
|
140
|
+
|
|
141
|
+
Returns:
|
|
142
|
+
--------
|
|
143
|
+
dict
|
|
144
|
+
Dictionary with hub-corrected networks: {'lr_sig': DataFrame, 'gr': DataFrame}
|
|
145
|
+
"""
|
|
146
|
+
# Input validation
|
|
147
|
+
if not isinstance(weighted_networks, dict):
|
|
148
|
+
raise TypeError("weighted_networks must be a dictionary")
|
|
149
|
+
if 'lr_sig' not in weighted_networks:
|
|
150
|
+
raise ValueError("weighted_networks must contain 'lr_sig' key")
|
|
151
|
+
if 'gr' not in weighted_networks:
|
|
152
|
+
raise ValueError("weighted_networks must contain 'gr' key")
|
|
153
|
+
|
|
154
|
+
if not isinstance(weighted_networks['lr_sig'], pd.DataFrame):
|
|
155
|
+
raise TypeError("weighted_networks['lr_sig'] must be a pandas DataFrame")
|
|
156
|
+
if not isinstance(weighted_networks['gr'], pd.DataFrame):
|
|
157
|
+
raise TypeError("weighted_networks['gr'] must be a pandas DataFrame")
|
|
158
|
+
|
|
159
|
+
if 'weight' not in weighted_networks['lr_sig'].columns:
|
|
160
|
+
raise ValueError("lr_sig must contain a column named 'weight'")
|
|
161
|
+
if 'weight' not in weighted_networks['gr'].columns:
|
|
162
|
+
raise ValueError("gr must contain a column named 'weight'")
|
|
163
|
+
|
|
164
|
+
if not (0 <= lr_sig_hub <= 1):
|
|
165
|
+
raise ValueError("lr_sig_hub must be between 0 and 1 (inclusive)")
|
|
166
|
+
if not (0 <= gr_hub <= 1):
|
|
167
|
+
raise ValueError("gr_hub must be between 0 and 1 (inclusive)")
|
|
168
|
+
|
|
169
|
+
ligand_signaling_network = weighted_networks['lr_sig'].copy()
|
|
170
|
+
regulatory_network = weighted_networks['gr'].copy()
|
|
171
|
+
|
|
172
|
+
# Apply hub correction to ligand-signaling network
|
|
173
|
+
if lr_sig_hub > 0:
|
|
174
|
+
# Count incoming edges (indegree) for each node
|
|
175
|
+
indegree = ligand_signaling_network.groupby('to', as_index=False).size()
|
|
176
|
+
indegree.columns = ['to', 'n']
|
|
177
|
+
|
|
178
|
+
# Merge indegree counts and apply correction
|
|
179
|
+
ligand_signaling_network = (
|
|
180
|
+
ligand_signaling_network
|
|
181
|
+
.merge(indegree, on='to', how='left')
|
|
182
|
+
.assign(weight=lambda x: x['weight'] / (x['n'] ** lr_sig_hub))
|
|
183
|
+
.drop(columns=['n'])
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
# Apply hub correction to gene regulatory network
|
|
187
|
+
if gr_hub > 0:
|
|
188
|
+
# Count incoming edges (indegree) for each node
|
|
189
|
+
indegree = regulatory_network.groupby('to', as_index=False).size()
|
|
190
|
+
indegree.columns = ['to', 'n']
|
|
191
|
+
|
|
192
|
+
# Merge indegree counts and apply correction
|
|
193
|
+
regulatory_network = (
|
|
194
|
+
regulatory_network
|
|
195
|
+
.merge(indegree, on='to', how='left')
|
|
196
|
+
.assign(weight=lambda x: x['weight'] / (x['n'] ** gr_hub))
|
|
197
|
+
.drop(columns=['n'])
|
|
198
|
+
)
|
|
199
|
+
|
|
200
|
+
return {
|
|
201
|
+
'lr_sig': ligand_signaling_network,
|
|
202
|
+
'gr': regulatory_network
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
def add_new_datasource(
|
|
207
|
+
new_source: pd.DataFrame,
|
|
208
|
+
network: Optional[pd.DataFrame],
|
|
209
|
+
new_weight: float,
|
|
210
|
+
source_weights_df: pd.DataFrame
|
|
211
|
+
) -> Tuple[pd.DataFrame, pd.DataFrame]:
|
|
212
|
+
"""
|
|
213
|
+
Add a new data source to one of the ligand-receptor, signaling or gene
|
|
214
|
+
regulatory data sources.
|
|
215
|
+
|
|
216
|
+
Parameters:
|
|
217
|
+
-----------
|
|
218
|
+
new_source : pd.DataFrame
|
|
219
|
+
Novel interactions (required columns: from, to, source)
|
|
220
|
+
network : pd.DataFrame or None
|
|
221
|
+
Base network to which to add the new data source (required columns: from, to, source)
|
|
222
|
+
If None, creates a new network
|
|
223
|
+
new_weight : float
|
|
224
|
+
Weight value between 0 and 1 to assign to the new data source
|
|
225
|
+
source_weights_df : pd.DataFrame
|
|
226
|
+
Weights associated to each already included data source (required columns: source, weight)
|
|
227
|
+
|
|
228
|
+
Returns:
|
|
229
|
+
--------
|
|
230
|
+
tuple
|
|
231
|
+
(updated_network, updated_source_weights_df)
|
|
232
|
+
"""
|
|
233
|
+
# Input validation
|
|
234
|
+
if not isinstance(new_source, pd.DataFrame):
|
|
235
|
+
raise TypeError("new_source must be a pandas DataFrame")
|
|
236
|
+
if network is not None and not isinstance(network, pd.DataFrame):
|
|
237
|
+
raise TypeError("network must be a pandas DataFrame or None")
|
|
238
|
+
if not isinstance(source_weights_df, pd.DataFrame):
|
|
239
|
+
raise TypeError("source_weights_df must be a pandas DataFrame")
|
|
240
|
+
|
|
241
|
+
if not (0 <= new_weight <= 1):
|
|
242
|
+
raise ValueError("new_weight must be between 0 and 1")
|
|
243
|
+
|
|
244
|
+
if (source_weights_df['weight'] > 1).any() or new_weight > 1:
|
|
245
|
+
raise ValueError("No data source weight may be higher than 1")
|
|
246
|
+
|
|
247
|
+
# Get unique source name(s) from new_source
|
|
248
|
+
new_source_names = new_source['source'].unique()
|
|
249
|
+
|
|
250
|
+
if network is None:
|
|
251
|
+
# Create new network
|
|
252
|
+
updated_network = new_source.copy()
|
|
253
|
+
updated_source_weights_df = pd.DataFrame({
|
|
254
|
+
'source': new_source_names,
|
|
255
|
+
'weight': [new_weight] * len(new_source_names)
|
|
256
|
+
})
|
|
257
|
+
else:
|
|
258
|
+
# Add to existing network
|
|
259
|
+
updated_network = pd.concat([network, new_source], ignore_index=True)
|
|
260
|
+
new_weights = pd.DataFrame({
|
|
261
|
+
'source': new_source_names,
|
|
262
|
+
'weight': [new_weight] * len(new_source_names)
|
|
263
|
+
})
|
|
264
|
+
updated_source_weights_df = pd.concat(
|
|
265
|
+
[source_weights_df, new_weights],
|
|
266
|
+
ignore_index=True
|
|
267
|
+
)
|
|
268
|
+
|
|
269
|
+
return updated_network, updated_source_weights_df
|
|
270
|
+
|