bonesistools 1.2.9__tar.gz → 1.3.0__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.
- {bonesistools-1.2.9 → bonesistools-1.3.0}/PKG-INFO +1 -1
- {bonesistools-1.2.9 → bonesistools-1.3.0}/pyproject.toml +1 -1
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/sctools/preprocessing/_hvg.py +365 -35
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/regression/sct/preprocessing/test_hvg.py +330 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/.gitignore +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/LICENSE +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/README.md +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/__init__.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/_compat.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/_metadata.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/_typing.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/_validation.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/_warnings.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/boolpy/__init__.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/boolpy/boolean_algebra/__init__.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/boolpy/boolean_algebra/_algebra.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/boolpy/boolean_algebra/_boolean.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/boolpy/boolean_algebra/_hypercube.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/boolpy/boolean_algebra/_kleene.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/boolpy/boolean_algebra/_parser.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/boolpy/boolean_algebra/_representation.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/boolpy/boolean_algebra/_structure.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/boolpy/boolean_algebra/_typing.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/boolpy/boolean_network/__init__.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/boolpy/boolean_network/_network.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/boolpy/boolean_network/_parser.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/boolpy/boolean_network/_typing.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/boolpy/influence_graph/__init__.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/boolpy/influence_graph/_algorithms.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/boolpy/influence_graph/_distances.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/boolpy/influence_graph/_influence_graph.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/boolpy/influence_graph/_parser.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/boolpy/influence_graph/_scoring.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/boolpy/influence_graph/_typing.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/boolpy/plotting/__init__.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/boolpy/plotting/_graphviz.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/boolpy/plotting/_styles.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/boolpy/plotting/_svg.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/databases/__init__.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/databases/hcop/__init__.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/databases/hcop/_orthologs.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/databases/hcop/data/human_anole_lizard_hcop.tsv.gz +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/databases/hcop/data/human_c.elegans_hcop.tsv.gz +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/databases/hcop/data/human_cat_hcop.tsv.gz +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/databases/hcop/data/human_cattle_hcop.tsv.gz +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/databases/hcop/data/human_chicken_hcop.tsv.gz +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/databases/hcop/data/human_chimpanzee_hcop.tsv.gz +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/databases/hcop/data/human_dog_hcop.tsv.gz +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/databases/hcop/data/human_fruitfly_hcop.tsv.gz +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/databases/hcop/data/human_horse_hcop.tsv.gz +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/databases/hcop/data/human_macaque_hcop.tsv.gz +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/databases/hcop/data/human_mouse_hcop.tsv.gz +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/databases/hcop/data/human_opossum_hcop.tsv.gz +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/databases/hcop/data/human_pig_hcop.tsv.gz +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/databases/hcop/data/human_platypus_hcop.tsv.gz +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/databases/hcop/data/human_rat_hcop.tsv.gz +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/databases/hcop/data/human_s.cerevisiae_hcop.tsv.gz +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/databases/hcop/data/human_s.pombe_hcop.tsv.gz +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/databases/hcop/data/human_xenopus_hcop.tsv.gz +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/databases/hcop/data/human_zebrafish_hcop.tsv.gz +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/databases/ncbi/__init__.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/databases/ncbi/_genesyn.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/databases/ncbi/_typing.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/databases/ncbi/data/gi/escherichia_coli_gene_info.tsv.gz +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/databases/ncbi/data/gi/homo_sapiens_gene_info.tsv.gz +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/databases/ncbi/data/gi/mus_musculus_gene_info.tsv.gz +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/databases/omnipath/__init__.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/databases/omnipath/_archive.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/databases/omnipath/_collectri.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/databases/omnipath/_dorothea.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/py.typed +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/sctools/__init__.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/sctools/_dependencies.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/sctools/_metadata.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/sctools/_stats.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/sctools/_typing.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/sctools/_validation.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/sctools/datasets/__init__.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/sctools/datasets/_geo.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/sctools/datasets/_metadata.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/sctools/datasets/_nestorowa.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/sctools/datasets/_pbmc3k.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/sctools/datasets/_registry.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/sctools/datasets/datasets.json +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/sctools/plotting/__init__.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/sctools/plotting/_barplot.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/sctools/plotting/_colors.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/sctools/plotting/_density.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/sctools/plotting/_distribution.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/sctools/plotting/_figure.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/sctools/plotting/_graph.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/sctools/plotting/_scatterplot.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/sctools/plotting/_typing.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/sctools/plotting/_utils.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/sctools/preprocessing/__init__.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/sctools/preprocessing/_classification.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/sctools/preprocessing/_duplicates.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/sctools/preprocessing/_filter.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/sctools/preprocessing/_genename.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/sctools/preprocessing/_qc.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/sctools/preprocessing/_simple.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/sctools/preprocessing/_transfer.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/sctools/preprocessing/_transform.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/sctools/tools/__init__.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/sctools/tools/_binarize.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/sctools/tools/_classification.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/sctools/tools/_clustering.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/sctools/tools/_conversion.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/sctools/tools/_embedding.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/sctools/tools/_graph.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/sctools/tools/_markers.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/sctools/tools/_maths.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/sctools/tools/_neighbors.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/sctools/tools/_regress.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/sctools/tools/_stats.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/sctools/tools/_utils.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/src/bonesistools/sctools/tools/_write.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/.placeholder +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/__init__.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/golden/LICENSE.txt +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/golden/README.md +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/golden/__init__.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/golden/_workflow.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/golden/conftest.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/golden/expected/hvg_binning.npz +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/golden/expected/hvg_loess.npz +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/golden/expected/neighbors.npz +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/golden/expected/pca.npz +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/golden/expected/qc.npz +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/golden/expected/spectral.npz +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/golden/expected/tsne.npz +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/golden/expected/umap.npz +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/golden/generate_expected.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/golden/pbmc3k.h5ad +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/golden/test_golden_workflow.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/golden/test_pbmc3k.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/regression/__init__.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/regression/bpy/conftest.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/regression/bpy/test_aggregated_influence_graph.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/regression/bpy/test_boolean_algebra.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/regression/bpy/test_boolean_network.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/regression/bpy/test_boolean_network_ensemble.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/regression/bpy/test_hypercube.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/regression/bpy/test_hypercube_collection.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/regression/bpy/test_influence_graph.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/regression/bpy/test_influence_graph_distances.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/regression/bpy/test_influence_graph_parser.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/regression/bpy/test_influence_graph_scoring.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/regression/bpy/test_partial_boolean.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/regression/bpy/test_plotting_styles.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/regression/dbs/test_hcop.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/regression/dbs/test_ncbi.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/regression/dbs/test_omnipath.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/regression/sct/__init__.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/regression/sct/conftest.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/regression/sct/datasets/test_geo.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/regression/sct/datasets/test_nestorowa.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/regression/sct/datasets/test_registry.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/regression/sct/plotting/test_barplot.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/regression/sct/plotting/test_colors.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/regression/sct/plotting/test_density.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/regression/sct/plotting/test_distribution.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/regression/sct/plotting/test_figure.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/regression/sct/plotting/test_graph.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/regression/sct/plotting/test_plotting_utils.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/regression/sct/plotting/test_scatterplot.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/regression/sct/preprocessing/test_classification.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/regression/sct/preprocessing/test_duplicates.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/regression/sct/preprocessing/test_genename.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/regression/sct/preprocessing/test_qc.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/regression/sct/preprocessing/test_simple.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/regression/sct/preprocessing/test_transfer_obs.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/regression/sct/preprocessing/test_transform.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/regression/sct/test_typing.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/regression/sct/tools/test_binarize.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/regression/sct/tools/test_clustering.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/regression/sct/tools/test_conversion.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/regression/sct/tools/test_embedding.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/regression/sct/tools/test_knnsc.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/regression/sct/tools/test_markers.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/regression/sct/tools/test_maths.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/regression/sct/tools/test_neighbors.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/regression/sct/tools/test_paga.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/regression/sct/tools/test_regress.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/regression/sct/tools/test_stats.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/regression/sct/tools/test_utils.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/regression/sct/tools/test_write.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/regression/sct/toy_data.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/regression/test_import.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/regression/test_validation.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/reproducibility/__init__.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/reproducibility/dorothea_current_mouse_A.sha256 +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/reproducibility/dorothea_legacy_mouse.sha256 +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/reproducibility/test_reproducibility_omnipath.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/reproducibility/test_reproducibility_stats.py +0 -0
- {bonesistools-1.2.9 → bonesistools-1.3.0}/tests/reproducibility/test_reproducibility_workflow.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: bonesistools
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.3.0
|
|
4
4
|
Summary: Bioinformatics toolkit for upstream and downstream analyses around the BoNesis framework
|
|
5
5
|
Project-URL: Repository, https://github.com/bnediction/bonesistools
|
|
6
6
|
Author: Théo Roncalli
|
|
@@ -5,7 +5,7 @@ build-backend = "hatchling.build"
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "bonesistools"
|
|
7
7
|
description = "Bioinformatics toolkit for upstream and downstream analyses around the BoNesis framework"
|
|
8
|
-
version = "1.
|
|
8
|
+
version = "1.3.0"
|
|
9
9
|
license = "CECILL-2.1"
|
|
10
10
|
credits = ["BNeDiction", "PEPR Santé Numérique 2030"]
|
|
11
11
|
authors = [
|
|
@@ -26,11 +26,18 @@ from ..tools._utils import get_expression
|
|
|
26
26
|
|
|
27
27
|
HVGMethod = Literal["loess", "binning"]
|
|
28
28
|
HVG_METHODS: Tuple[HVGMethod, ...] = ("loess", "binning")
|
|
29
|
+
HVG_BATCH_WEIGHTINGS: Tuple[Literal["equal", "cell_count"], ...] = (
|
|
30
|
+
"equal",
|
|
31
|
+
"cell_count",
|
|
32
|
+
)
|
|
33
|
+
HVG_BATCH_SELECTIONS: Tuple[Literal["consensus", "rank"], ...] = (
|
|
34
|
+
"consensus",
|
|
35
|
+
"rank",
|
|
36
|
+
)
|
|
29
37
|
_DEFAULT_SCORE_CUTOFFS = {
|
|
30
38
|
"loess": (2.0, np.inf),
|
|
31
39
|
"binning": (0.5, np.inf),
|
|
32
40
|
}
|
|
33
|
-
_DEFAULT_MEAN_CUTOFF = (0.0125, 3.0)
|
|
34
41
|
_NORMAL_CONSISTENCY_MAD_SCALE = 0.6744897501960817
|
|
35
42
|
|
|
36
43
|
|
|
@@ -41,6 +48,15 @@ class _HVGScore:
|
|
|
41
48
|
scores: np.ndarray
|
|
42
49
|
|
|
43
50
|
|
|
51
|
+
@dataclass(frozen=True)
|
|
52
|
+
class _BatchHVGScore:
|
|
53
|
+
|
|
54
|
+
means: np.ndarray
|
|
55
|
+
scores: np.ndarray
|
|
56
|
+
nbatches: np.ndarray
|
|
57
|
+
rank_summary: np.ndarray
|
|
58
|
+
|
|
59
|
+
|
|
44
60
|
@dataclass(frozen=True)
|
|
45
61
|
class _HVGSelection:
|
|
46
62
|
|
|
@@ -50,6 +66,13 @@ class _HVGSelection:
|
|
|
50
66
|
mean_cutoff: Optional[Tuple[float, float]]
|
|
51
67
|
|
|
52
68
|
|
|
69
|
+
@dataclass(frozen=True)
|
|
70
|
+
class _BatchGroups:
|
|
71
|
+
|
|
72
|
+
masks: Tuple[np.ndarray, ...]
|
|
73
|
+
sizes: np.ndarray
|
|
74
|
+
|
|
75
|
+
|
|
53
76
|
@dataclass(frozen=True)
|
|
54
77
|
class _ClippedMoments:
|
|
55
78
|
|
|
@@ -65,12 +88,15 @@ def hvg(
|
|
|
65
88
|
adata: AnnData,
|
|
66
89
|
*,
|
|
67
90
|
expression: Optional[str] = None,
|
|
91
|
+
method: Literal["loess", "binning"] = "loess",
|
|
68
92
|
n_features: Optional[int] = 2000,
|
|
69
|
-
|
|
93
|
+
mean: Tuple[float, float] = (0.0125, 3.0),
|
|
94
|
+
score: Union[Literal["auto"], Tuple[float, float]] = "auto",
|
|
70
95
|
span: float = 0.3,
|
|
71
96
|
n_bins: int = 20,
|
|
72
|
-
|
|
73
|
-
|
|
97
|
+
batch_key: Optional[str] = None,
|
|
98
|
+
batch_selection: Literal["consensus", "rank"] = "consensus",
|
|
99
|
+
batch_weighting: Literal["equal", "cell_count"] = "equal",
|
|
74
100
|
key_added: str = "highly_variable",
|
|
75
101
|
copy: Literal[False] = False,
|
|
76
102
|
) -> None: ...
|
|
@@ -81,12 +107,15 @@ def hvg(
|
|
|
81
107
|
adata: AnnData,
|
|
82
108
|
*,
|
|
83
109
|
expression: Optional[str] = None,
|
|
110
|
+
method: Literal["loess", "binning"] = "loess",
|
|
84
111
|
n_features: Optional[int] = 2000,
|
|
85
|
-
|
|
112
|
+
mean: Tuple[float, float] = (0.0125, 3.0),
|
|
113
|
+
score: Union[Literal["auto"], Tuple[float, float]] = "auto",
|
|
86
114
|
span: float = 0.3,
|
|
87
115
|
n_bins: int = 20,
|
|
88
|
-
|
|
89
|
-
|
|
116
|
+
batch_key: Optional[str] = None,
|
|
117
|
+
batch_selection: Literal["consensus", "rank"] = "consensus",
|
|
118
|
+
batch_weighting: Literal["equal", "cell_count"] = "equal",
|
|
90
119
|
key_added: str = "highly_variable",
|
|
91
120
|
copy: Literal[True],
|
|
92
121
|
) -> AnnData: ...
|
|
@@ -97,12 +126,15 @@ def hvg(
|
|
|
97
126
|
adata: AnnData,
|
|
98
127
|
*,
|
|
99
128
|
expression: Optional[str] = None,
|
|
129
|
+
method: Literal["loess", "binning"] = "loess",
|
|
100
130
|
n_features: Optional[int] = 2000,
|
|
101
|
-
|
|
131
|
+
mean: Tuple[float, float] = (0.0125, 3.0),
|
|
132
|
+
score: Union[Literal["auto"], Tuple[float, float]] = "auto",
|
|
102
133
|
span: float = 0.3,
|
|
103
134
|
n_bins: int = 20,
|
|
104
|
-
|
|
105
|
-
|
|
135
|
+
batch_key: Optional[str] = None,
|
|
136
|
+
batch_selection: Literal["consensus", "rank"] = "consensus",
|
|
137
|
+
batch_weighting: Literal["equal", "cell_count"] = "equal",
|
|
106
138
|
key_added: str = "highly_variable",
|
|
107
139
|
copy: bool = False,
|
|
108
140
|
) -> Optional[AnnData]: ...
|
|
@@ -113,12 +145,15 @@ def hvg(
|
|
|
113
145
|
adata: AnnData,
|
|
114
146
|
*,
|
|
115
147
|
expression: Optional[str] = None,
|
|
148
|
+
method: Literal["loess", "binning"] = "loess",
|
|
116
149
|
n_features: Optional[int] = 2000,
|
|
117
|
-
|
|
150
|
+
mean: Tuple[float, float] = (0.0125, 3.0),
|
|
151
|
+
score: Union[Literal["auto"], Tuple[float, float]] = "auto",
|
|
118
152
|
span: float = 0.3,
|
|
119
153
|
n_bins: int = 20,
|
|
120
|
-
|
|
121
|
-
|
|
154
|
+
batch_key: Optional[str] = None,
|
|
155
|
+
batch_selection: Literal["consensus", "rank"] = "consensus",
|
|
156
|
+
batch_weighting: Literal["equal", "cell_count"] = "equal",
|
|
122
157
|
key_added: str = "highly_variable",
|
|
123
158
|
copy: bool = False,
|
|
124
159
|
) -> Optional[AnnData]:
|
|
@@ -134,9 +169,6 @@ def hvg(
|
|
|
134
169
|
`adata.X`; otherwise, use `adata.layers[expression]`. Use raw counts
|
|
135
170
|
for `method='loess'` and log-normalized expression values for
|
|
136
171
|
`method='binning'`.
|
|
137
|
-
n_features: int or None (default: 2000)
|
|
138
|
-
Number of highly variable features to select. If None, features are
|
|
139
|
-
selected using `score` and `mean` cutoffs instead.
|
|
140
172
|
method: {'loess', 'binning'} (default: 'loess')
|
|
141
173
|
Method used to score highly variable features.
|
|
142
174
|
|
|
@@ -151,18 +183,9 @@ def hvg(
|
|
|
151
183
|
grouped by mean expression, dispersions are normalized within
|
|
152
184
|
each bin using the median and median absolute deviation, and
|
|
153
185
|
features are ranked by normalized dispersion scores [2, 3].
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
n_bins: int (default: 20)
|
|
158
|
-
Number of mean-expression bins used by `method='binning'`.
|
|
159
|
-
score: {'auto'} or tuple of float (default: 'auto')
|
|
160
|
-
Score interval used when `n_features=None`. Features are selected when
|
|
161
|
-
`score[0] < feature_score < score[1]`. If 'auto', use
|
|
162
|
-
method-specific defaults: `(2.0, np.inf)` for `method='loess'` and
|
|
163
|
-
`(0.5, np.inf)` for `method='binning'`. For `method='loess'`, scores
|
|
164
|
-
are normalized variance scores. For `method='binning'`, scores are
|
|
165
|
-
normalized dispersion scores.
|
|
186
|
+
n_features: int or None (default: 2000)
|
|
187
|
+
Number of highly variable features to select. If None, features are
|
|
188
|
+
selected using `score` and `mean` cutoffs instead.
|
|
166
189
|
mean: tuple of float (default: (0.0125, 3.0))
|
|
167
190
|
Mean-expression interval used when `n_features=None`. Features are
|
|
168
191
|
selected when `mean[0] < feature_mean < mean[1]`. For
|
|
@@ -170,6 +193,34 @@ def hvg(
|
|
|
170
193
|
library-size-normalized counts with target sum 1e4. For
|
|
171
194
|
`method='binning'`, the interval is applied to the mean of the
|
|
172
195
|
provided expression matrix.
|
|
196
|
+
score: {'auto'} or tuple of float (default: 'auto')
|
|
197
|
+
Score interval used when `n_features=None`. Features are selected when
|
|
198
|
+
`score[0] < feature_score < score[1]`. If 'auto', use
|
|
199
|
+
method-specific defaults: `(2.0, np.inf)` for `method='loess'` and
|
|
200
|
+
`(0.5, np.inf)` for `method='binning'`. For `method='loess'`, scores
|
|
201
|
+
are normalized variance scores. For `method='binning'`, scores are
|
|
202
|
+
normalized dispersion scores.
|
|
203
|
+
span: float (default: 0.3)
|
|
204
|
+
LOESS smoothing span. Must be greater than 0 and smaller than or equal
|
|
205
|
+
to 1. Used by `method='loess'`.
|
|
206
|
+
n_bins: int (default: 20)
|
|
207
|
+
Number of mean-expression bins used by `method='binning'`.
|
|
208
|
+
batch_key: str, optional
|
|
209
|
+
Column in `adata.obs` defining batches. If provided, features are
|
|
210
|
+
scored independently in each batch and scores are averaged across
|
|
211
|
+
batches.
|
|
212
|
+
batch_selection: {'consensus', 'rank'} (default: 'consensus')
|
|
213
|
+
Batch-aware top-feature selection strategy used when both `batch_key`
|
|
214
|
+
and `n_features` are provided. If 'consensus', prioritize features
|
|
215
|
+
selected in the largest number of batches. If 'rank', prioritize
|
|
216
|
+
features with the best summarized within-batch rank.
|
|
217
|
+
batch_weighting: {'equal', 'cell_count'} (default: 'equal')
|
|
218
|
+
Batch score aggregation strategy. If 'equal', each batch has the same
|
|
219
|
+
weight. If 'cell_count', batches are weighted by their number of
|
|
220
|
+
observations. When `n_features` is provided, features selected in more
|
|
221
|
+
batches are prioritized before applying method-specific tie-breaks. If
|
|
222
|
+
`n_features` is None, cutoffs are applied to the aggregated scores and
|
|
223
|
+
means. Ignored when `batch_key` is None.
|
|
173
224
|
key_added: str (default: 'highly_variable')
|
|
174
225
|
Column in `adata.var` where the selected feature mask is stored.
|
|
175
226
|
copy: bool (default: False)
|
|
@@ -208,6 +259,23 @@ def hvg(
|
|
|
208
259
|
else _as_positive_integer(n_features, "n_features")
|
|
209
260
|
)
|
|
210
261
|
method = cast(HVGMethod, _as_literal(method, choices=HVG_METHODS, name="method"))
|
|
262
|
+
batch_key = None if batch_key is None else _as_string(batch_key, "batch_key")
|
|
263
|
+
batch_weighting = cast(
|
|
264
|
+
Literal["equal", "cell_count"],
|
|
265
|
+
_as_literal(
|
|
266
|
+
batch_weighting,
|
|
267
|
+
choices=HVG_BATCH_WEIGHTINGS,
|
|
268
|
+
name="batch_weighting",
|
|
269
|
+
),
|
|
270
|
+
)
|
|
271
|
+
batch_selection = cast(
|
|
272
|
+
Literal["consensus", "rank"],
|
|
273
|
+
_as_literal(
|
|
274
|
+
batch_selection,
|
|
275
|
+
choices=HVG_BATCH_SELECTIONS,
|
|
276
|
+
name="batch_selection",
|
|
277
|
+
),
|
|
278
|
+
)
|
|
211
279
|
span = _as_positive_number(span, "span")
|
|
212
280
|
if span > 1:
|
|
213
281
|
raise ValueError(
|
|
@@ -224,7 +292,7 @@ def hvg(
|
|
|
224
292
|
n_features is not None
|
|
225
293
|
and (
|
|
226
294
|
score_cutoff is not None
|
|
227
|
-
or mean_cutoff !=
|
|
295
|
+
or mean_cutoff != (0.0125, 3.0)
|
|
228
296
|
)
|
|
229
297
|
):
|
|
230
298
|
warnings.warn(
|
|
@@ -244,18 +312,41 @@ def hvg(
|
|
|
244
312
|
if len(expression_mtx.shape) != 2:
|
|
245
313
|
raise ValueError("invalid expression matrix: expected a two-dimensional matrix")
|
|
246
314
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
315
|
+
batch_groups = _resolve_batch_groups(adata, batch_key)
|
|
316
|
+
scoring = (
|
|
317
|
+
_score_hvg_features(
|
|
318
|
+
expression_mtx,
|
|
319
|
+
method=method,
|
|
320
|
+
span=span,
|
|
321
|
+
n_bins=n_bins,
|
|
322
|
+
)
|
|
323
|
+
if batch_groups is None
|
|
324
|
+
else _score_hvg_features_by_batch(
|
|
325
|
+
expression_mtx,
|
|
326
|
+
batch_groups=batch_groups,
|
|
327
|
+
batch_weighting=batch_weighting,
|
|
328
|
+
n_features=n_features,
|
|
329
|
+
method=method,
|
|
330
|
+
span=span,
|
|
331
|
+
n_bins=n_bins,
|
|
332
|
+
)
|
|
333
|
+
)
|
|
334
|
+
ordered_indices = (
|
|
335
|
+
_order_by_score(scoring.scores)
|
|
336
|
+
if batch_groups is None or n_features is None
|
|
337
|
+
else _order_batch_hvg_features(
|
|
338
|
+
cast(_BatchHVGScore, scoring),
|
|
339
|
+
method=method,
|
|
340
|
+
batch_selection=batch_selection,
|
|
341
|
+
)
|
|
252
342
|
)
|
|
253
|
-
ordered_indices = _order_by_score(scoring.scores)
|
|
254
343
|
selection_means = (
|
|
255
344
|
_selection_means(
|
|
256
345
|
expression_mtx,
|
|
257
346
|
method=method,
|
|
258
347
|
scoring_means=scoring.means,
|
|
348
|
+
batch_groups=batch_groups,
|
|
349
|
+
batch_weighting=batch_weighting,
|
|
259
350
|
)
|
|
260
351
|
if n_features is None
|
|
261
352
|
else scoring.means
|
|
@@ -285,6 +376,9 @@ def hvg(
|
|
|
285
376
|
n_bins=n_bins,
|
|
286
377
|
n_features=n_features,
|
|
287
378
|
selection=selection,
|
|
379
|
+
batch_key=batch_key,
|
|
380
|
+
batch_weighting=batch_weighting,
|
|
381
|
+
batch_selection=batch_selection,
|
|
288
382
|
),
|
|
289
383
|
}
|
|
290
384
|
|
|
@@ -313,6 +407,62 @@ def _score_hvg_features(
|
|
|
313
407
|
raise ValueError(f"unsupported HVG method: {method!r}")
|
|
314
408
|
|
|
315
409
|
|
|
410
|
+
def _score_hvg_features_by_batch(
|
|
411
|
+
matrix: Matrix,
|
|
412
|
+
*,
|
|
413
|
+
batch_groups: _BatchGroups,
|
|
414
|
+
batch_weighting: Literal["equal", "cell_count"],
|
|
415
|
+
n_features: Optional[int],
|
|
416
|
+
method: HVGMethod,
|
|
417
|
+
span: float,
|
|
418
|
+
n_bins: int,
|
|
419
|
+
) -> _BatchHVGScore:
|
|
420
|
+
|
|
421
|
+
batch_means = []
|
|
422
|
+
batch_scores = []
|
|
423
|
+
batch_ranks = []
|
|
424
|
+
nbatches = np.zeros(matrix.shape[1], dtype=int)
|
|
425
|
+
for mask in batch_groups.masks:
|
|
426
|
+
batch_matrix = _subset_obs_matrix(matrix, mask)
|
|
427
|
+
if int(mask.sum()) < 2:
|
|
428
|
+
batch_means.append(_compute_mean(batch_matrix))
|
|
429
|
+
batch_scores.append(np.full(matrix.shape[1], np.nan, dtype=np.float64))
|
|
430
|
+
batch_ranks.append(np.full(matrix.shape[1], np.nan, dtype=np.float64))
|
|
431
|
+
continue
|
|
432
|
+
|
|
433
|
+
scoring = _score_hvg_features(
|
|
434
|
+
batch_matrix,
|
|
435
|
+
method=method,
|
|
436
|
+
span=span,
|
|
437
|
+
n_bins=n_bins,
|
|
438
|
+
)
|
|
439
|
+
batch_means.append(scoring.means)
|
|
440
|
+
batch_scores.append(scoring.scores)
|
|
441
|
+
batch_rank = np.full(matrix.shape[1], np.nan, dtype=np.float64)
|
|
442
|
+
if n_features is not None:
|
|
443
|
+
selected_indices = _order_by_score(scoring.scores)[:n_features]
|
|
444
|
+
nbatches[selected_indices] += 1
|
|
445
|
+
batch_rank[selected_indices] = np.arange(
|
|
446
|
+
1,
|
|
447
|
+
selected_indices.size + 1,
|
|
448
|
+
dtype=np.float64,
|
|
449
|
+
)
|
|
450
|
+
batch_ranks.append(batch_rank)
|
|
451
|
+
|
|
452
|
+
weights = _batch_weights(batch_groups, batch_weighting=batch_weighting)
|
|
453
|
+
|
|
454
|
+
return _BatchHVGScore(
|
|
455
|
+
means=_weighted_nanmean(np.vstack(batch_means), weights),
|
|
456
|
+
scores=_weighted_nanmean(np.vstack(batch_scores), weights),
|
|
457
|
+
nbatches=nbatches,
|
|
458
|
+
rank_summary=_batch_rank_summary(
|
|
459
|
+
np.vstack(batch_ranks),
|
|
460
|
+
weights,
|
|
461
|
+
batch_weighting=batch_weighting,
|
|
462
|
+
),
|
|
463
|
+
)
|
|
464
|
+
|
|
465
|
+
|
|
316
466
|
def _hvg_params(
|
|
317
467
|
*,
|
|
318
468
|
method: HVGMethod,
|
|
@@ -320,12 +470,18 @@ def _hvg_params(
|
|
|
320
470
|
n_bins: int,
|
|
321
471
|
n_features: Optional[int],
|
|
322
472
|
selection: _HVGSelection,
|
|
473
|
+
batch_key: Optional[str],
|
|
474
|
+
batch_weighting: Literal["equal", "cell_count"],
|
|
475
|
+
batch_selection: Literal["consensus", "rank"],
|
|
323
476
|
) -> dict:
|
|
324
477
|
|
|
325
478
|
params = {
|
|
326
479
|
"selection": "top_n" if n_features is not None else "cutoff",
|
|
327
480
|
"score_cutoff": selection.score_cutoff,
|
|
328
481
|
"mean_cutoff": selection.mean_cutoff,
|
|
482
|
+
"batch_key": batch_key,
|
|
483
|
+
"batch_weighting": batch_weighting,
|
|
484
|
+
"batch_selection": batch_selection,
|
|
329
485
|
}
|
|
330
486
|
if method == "loess":
|
|
331
487
|
return {
|
|
@@ -407,9 +563,17 @@ def _selection_means(
|
|
|
407
563
|
*,
|
|
408
564
|
method: HVGMethod,
|
|
409
565
|
scoring_means: np.ndarray,
|
|
566
|
+
batch_groups: Optional[_BatchGroups],
|
|
567
|
+
batch_weighting: Literal["equal", "cell_count"],
|
|
410
568
|
) -> np.ndarray:
|
|
411
569
|
|
|
412
570
|
if method == "loess":
|
|
571
|
+
if batch_groups is not None:
|
|
572
|
+
return _compute_log_normalized_mean_by_batch(
|
|
573
|
+
matrix,
|
|
574
|
+
batch_groups=batch_groups,
|
|
575
|
+
batch_weighting=batch_weighting,
|
|
576
|
+
)
|
|
413
577
|
return _compute_log_normalized_mean(matrix)
|
|
414
578
|
return scoring_means
|
|
415
579
|
|
|
@@ -463,6 +627,22 @@ def _compute_log_normalized_mean(
|
|
|
463
627
|
return np.asarray(normalized.mean(axis=0, dtype=np.float64)).ravel()
|
|
464
628
|
|
|
465
629
|
|
|
630
|
+
def _compute_log_normalized_mean_by_batch(
|
|
631
|
+
matrix: Matrix,
|
|
632
|
+
*,
|
|
633
|
+
batch_groups: _BatchGroups,
|
|
634
|
+
batch_weighting: Literal["equal", "cell_count"],
|
|
635
|
+
) -> np.ndarray:
|
|
636
|
+
|
|
637
|
+
batch_means = [
|
|
638
|
+
_compute_log_normalized_mean(_subset_obs_matrix(matrix, mask))
|
|
639
|
+
for mask in batch_groups.masks
|
|
640
|
+
]
|
|
641
|
+
weights = _batch_weights(batch_groups, batch_weighting=batch_weighting)
|
|
642
|
+
|
|
643
|
+
return _weighted_nanmean(np.vstack(batch_means), weights)
|
|
644
|
+
|
|
645
|
+
|
|
466
646
|
def _compute_variance(
|
|
467
647
|
matrix: Matrix,
|
|
468
648
|
mean: Optional[np.ndarray] = None,
|
|
@@ -673,6 +853,156 @@ def _order_by_score(scores: np.ndarray) -> np.ndarray:
|
|
|
673
853
|
return eligible[np.argsort(-scores[eligible], kind="mergesort")]
|
|
674
854
|
|
|
675
855
|
|
|
856
|
+
def _order_batch_hvg_features(
|
|
857
|
+
scoring: _BatchHVGScore,
|
|
858
|
+
*,
|
|
859
|
+
method: HVGMethod,
|
|
860
|
+
batch_selection: Literal["consensus", "rank"],
|
|
861
|
+
) -> np.ndarray:
|
|
862
|
+
|
|
863
|
+
eligible = np.flatnonzero(np.isfinite(scoring.scores))
|
|
864
|
+
ranks = np.where(
|
|
865
|
+
np.isnan(scoring.rank_summary),
|
|
866
|
+
np.inf,
|
|
867
|
+
scoring.rank_summary,
|
|
868
|
+
)
|
|
869
|
+
if batch_selection == "rank":
|
|
870
|
+
return eligible[
|
|
871
|
+
np.lexsort(
|
|
872
|
+
(
|
|
873
|
+
-scoring.scores[eligible],
|
|
874
|
+
-scoring.nbatches[eligible],
|
|
875
|
+
ranks[eligible],
|
|
876
|
+
)
|
|
877
|
+
)
|
|
878
|
+
]
|
|
879
|
+
|
|
880
|
+
if batch_selection != "consensus":
|
|
881
|
+
raise ValueError(f"unsupported batch selection: {batch_selection!r}")
|
|
882
|
+
|
|
883
|
+
if method == "loess":
|
|
884
|
+
return eligible[
|
|
885
|
+
np.lexsort(
|
|
886
|
+
(
|
|
887
|
+
-scoring.scores[eligible],
|
|
888
|
+
ranks[eligible],
|
|
889
|
+
-scoring.nbatches[eligible],
|
|
890
|
+
)
|
|
891
|
+
)
|
|
892
|
+
]
|
|
893
|
+
|
|
894
|
+
if method == "binning":
|
|
895
|
+
return eligible[
|
|
896
|
+
np.lexsort(
|
|
897
|
+
(
|
|
898
|
+
-scoring.scores[eligible],
|
|
899
|
+
-scoring.nbatches[eligible],
|
|
900
|
+
)
|
|
901
|
+
)
|
|
902
|
+
]
|
|
903
|
+
|
|
904
|
+
raise ValueError(f"unsupported HVG method: {method!r}")
|
|
905
|
+
|
|
906
|
+
|
|
907
|
+
def _resolve_batch_groups(
|
|
908
|
+
adata: AnnData,
|
|
909
|
+
batch_key: Optional[str],
|
|
910
|
+
) -> Optional[_BatchGroups]:
|
|
911
|
+
|
|
912
|
+
if batch_key is None:
|
|
913
|
+
return None
|
|
914
|
+
if batch_key not in adata.obs:
|
|
915
|
+
raise KeyError(f"column {batch_key!r} not found in adata.obs")
|
|
916
|
+
|
|
917
|
+
labels = cast(Any, adata.obs[batch_key])
|
|
918
|
+
valid_mask = ~np.asarray(labels.isna(), dtype=bool)
|
|
919
|
+
values = list(labels[valid_mask].unique())
|
|
920
|
+
masks = tuple(
|
|
921
|
+
np.asarray((labels == value) & valid_mask, dtype=bool)
|
|
922
|
+
for value in values
|
|
923
|
+
)
|
|
924
|
+
masks = tuple(mask for mask in masks if np.any(mask))
|
|
925
|
+
if not masks:
|
|
926
|
+
raise ValueError(
|
|
927
|
+
f"invalid observation batches in adata.obs[{batch_key!r}]: "
|
|
928
|
+
"expected at least one non-missing batch"
|
|
929
|
+
)
|
|
930
|
+
|
|
931
|
+
return _BatchGroups(
|
|
932
|
+
masks=masks,
|
|
933
|
+
sizes=np.asarray([mask.sum() for mask in masks], dtype=np.float64),
|
|
934
|
+
)
|
|
935
|
+
|
|
936
|
+
|
|
937
|
+
def _subset_obs_matrix(matrix: Matrix, obs_mask: np.ndarray) -> Matrix:
|
|
938
|
+
|
|
939
|
+
return cast(Matrix, cast(Any, matrix)[obs_mask, :])
|
|
940
|
+
|
|
941
|
+
|
|
942
|
+
def _batch_weights(
|
|
943
|
+
batch_groups: _BatchGroups,
|
|
944
|
+
*,
|
|
945
|
+
batch_weighting: Literal["equal", "cell_count"],
|
|
946
|
+
) -> np.ndarray:
|
|
947
|
+
|
|
948
|
+
if batch_weighting == "equal":
|
|
949
|
+
return np.ones(batch_groups.sizes.shape[0], dtype=np.float64)
|
|
950
|
+
if batch_weighting == "cell_count":
|
|
951
|
+
return batch_groups.sizes.astype(np.float64, copy=False)
|
|
952
|
+
|
|
953
|
+
raise ValueError(f"unsupported batch weighting: {batch_weighting!r}")
|
|
954
|
+
|
|
955
|
+
|
|
956
|
+
def _weighted_nanmean(values: np.ndarray, weights: np.ndarray) -> np.ndarray:
|
|
957
|
+
|
|
958
|
+
valid = ~np.isnan(values)
|
|
959
|
+
weighted_values = np.where(valid, values, 0.0) * weights.reshape(-1, 1)
|
|
960
|
+
denominators = np.sum(valid * weights.reshape(-1, 1), axis=0)
|
|
961
|
+
|
|
962
|
+
return np.divide(
|
|
963
|
+
weighted_values.sum(axis=0),
|
|
964
|
+
denominators,
|
|
965
|
+
out=np.full(values.shape[1], np.nan, dtype=np.float64),
|
|
966
|
+
where=denominators != 0,
|
|
967
|
+
)
|
|
968
|
+
|
|
969
|
+
|
|
970
|
+
def _batch_rank_summary(
|
|
971
|
+
ranks: np.ndarray,
|
|
972
|
+
weights: np.ndarray,
|
|
973
|
+
*,
|
|
974
|
+
batch_weighting: Literal["equal", "cell_count"],
|
|
975
|
+
) -> np.ndarray:
|
|
976
|
+
|
|
977
|
+
if batch_weighting == "equal":
|
|
978
|
+
return cast(
|
|
979
|
+
np.ndarray,
|
|
980
|
+
np.ma.median(np.ma.masked_invalid(ranks), axis=0).filled(np.nan),
|
|
981
|
+
)
|
|
982
|
+
|
|
983
|
+
return _weighted_nanmedian(ranks, weights)
|
|
984
|
+
|
|
985
|
+
|
|
986
|
+
def _weighted_nanmedian(values: np.ndarray, weights: np.ndarray) -> np.ndarray:
|
|
987
|
+
|
|
988
|
+
medians = np.full(values.shape[1], np.nan, dtype=np.float64)
|
|
989
|
+
for index in range(values.shape[1]):
|
|
990
|
+
valid = ~np.isnan(values[:, index])
|
|
991
|
+
if not np.any(valid):
|
|
992
|
+
continue
|
|
993
|
+
|
|
994
|
+
valid_values = values[valid, index]
|
|
995
|
+
valid_weights = weights[valid]
|
|
996
|
+
order = np.argsort(valid_values, kind="mergesort")
|
|
997
|
+
sorted_values = valid_values[order]
|
|
998
|
+
cumulative_weights = np.cumsum(valid_weights[order])
|
|
999
|
+
cutoff = 0.5 * cumulative_weights[-1]
|
|
1000
|
+
median_index = np.searchsorted(cumulative_weights, cutoff, side="left")
|
|
1001
|
+
medians[index] = sorted_values[median_index]
|
|
1002
|
+
|
|
1003
|
+
return medians
|
|
1004
|
+
|
|
1005
|
+
|
|
676
1006
|
def _as_cutoff_interval(
|
|
677
1007
|
value: Tuple[float, float],
|
|
678
1008
|
name: str,
|