bonesistools 1.2.8__tar.gz → 1.2.9__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.8 → bonesistools-1.2.9}/PKG-INFO +1 -1
- {bonesistools-1.2.8 → bonesistools-1.2.9}/pyproject.toml +1 -1
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/sctools/datasets/_geo.py +19 -6
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/sctools/datasets/_registry.py +85 -3
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/sctools/datasets/datasets.json +1 -1
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/sctools/plotting/_barplot.py +175 -147
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/sctools/plotting/_density.py +19 -52
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/sctools/plotting/_distribution.py +1292 -1253
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/sctools/plotting/_graph.py +3 -7
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/sctools/plotting/_scatterplot.py +627 -653
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/sctools/plotting/_utils.py +71 -2
- bonesistools-1.2.9/src/bonesistools/sctools/preprocessing/_hvg.py +846 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/sctools/preprocessing/_qc.py +39 -38
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/sctools/preprocessing/_transform.py +85 -33
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/sctools/tools/_neighbors.py +31 -7
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/sctools/tools/_stats.py +97 -80
- {bonesistools-1.2.8 → bonesistools-1.2.9}/tests/golden/README.md +10 -1
- {bonesistools-1.2.8 → bonesistools-1.2.9}/tests/golden/_workflow.py +62 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/tests/golden/conftest.py +9 -1
- bonesistools-1.2.9/tests/golden/expected/hvg_binning.npz +0 -0
- bonesistools-1.2.9/tests/golden/expected/spectral.npz +0 -0
- bonesistools-1.2.9/tests/golden/expected/tsne.npz +0 -0
- bonesistools-1.2.9/tests/golden/expected/umap.npz +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/tests/golden/test_golden_workflow.py +8 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/tests/regression/bpy/test_boolean_algebra.py +38 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/tests/regression/sct/datasets/test_geo.py +286 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/tests/regression/sct/datasets/test_nestorowa.py +18 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/tests/regression/sct/datasets/test_registry.py +36 -1
- bonesistools-1.2.9/tests/regression/sct/plotting/test_plotting_utils.py +212 -0
- bonesistools-1.2.9/tests/regression/sct/preprocessing/test_hvg.py +531 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/tests/regression/sct/preprocessing/test_qc.py +58 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/tests/regression/sct/preprocessing/test_simple.py +46 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/tests/regression/sct/tools/test_neighbors.py +118 -0
- bonesistools-1.2.9/tests/regression/test_import.py +77 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/tests/reproducibility/test_reproducibility_workflow.py +21 -0
- bonesistools-1.2.8/src/bonesistools/sctools/preprocessing/_hvg.py +0 -407
- bonesistools-1.2.8/tests/regression/sct/preprocessing/test_hvg.py +0 -240
- bonesistools-1.2.8/tests/regression/test_import.py +0 -24
- {bonesistools-1.2.8 → bonesistools-1.2.9}/.gitignore +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/LICENSE +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/README.md +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/__init__.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/_compat.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/_metadata.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/_typing.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/_validation.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/_warnings.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/boolpy/__init__.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/boolpy/boolean_algebra/__init__.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/boolpy/boolean_algebra/_algebra.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/boolpy/boolean_algebra/_boolean.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/boolpy/boolean_algebra/_hypercube.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/boolpy/boolean_algebra/_kleene.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/boolpy/boolean_algebra/_parser.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/boolpy/boolean_algebra/_representation.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/boolpy/boolean_algebra/_structure.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/boolpy/boolean_algebra/_typing.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/boolpy/boolean_network/__init__.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/boolpy/boolean_network/_network.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/boolpy/boolean_network/_parser.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/boolpy/boolean_network/_typing.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/boolpy/influence_graph/__init__.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/boolpy/influence_graph/_algorithms.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/boolpy/influence_graph/_distances.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/boolpy/influence_graph/_influence_graph.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/boolpy/influence_graph/_parser.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/boolpy/influence_graph/_scoring.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/boolpy/influence_graph/_typing.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/boolpy/plotting/__init__.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/boolpy/plotting/_graphviz.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/boolpy/plotting/_styles.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/boolpy/plotting/_svg.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/databases/__init__.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/databases/hcop/__init__.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/databases/hcop/_orthologs.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/databases/hcop/data/human_anole_lizard_hcop.tsv.gz +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/databases/hcop/data/human_c.elegans_hcop.tsv.gz +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/databases/hcop/data/human_cat_hcop.tsv.gz +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/databases/hcop/data/human_cattle_hcop.tsv.gz +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/databases/hcop/data/human_chicken_hcop.tsv.gz +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/databases/hcop/data/human_chimpanzee_hcop.tsv.gz +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/databases/hcop/data/human_dog_hcop.tsv.gz +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/databases/hcop/data/human_fruitfly_hcop.tsv.gz +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/databases/hcop/data/human_horse_hcop.tsv.gz +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/databases/hcop/data/human_macaque_hcop.tsv.gz +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/databases/hcop/data/human_mouse_hcop.tsv.gz +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/databases/hcop/data/human_opossum_hcop.tsv.gz +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/databases/hcop/data/human_pig_hcop.tsv.gz +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/databases/hcop/data/human_platypus_hcop.tsv.gz +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/databases/hcop/data/human_rat_hcop.tsv.gz +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/databases/hcop/data/human_s.cerevisiae_hcop.tsv.gz +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/databases/hcop/data/human_s.pombe_hcop.tsv.gz +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/databases/hcop/data/human_xenopus_hcop.tsv.gz +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/databases/hcop/data/human_zebrafish_hcop.tsv.gz +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/databases/ncbi/__init__.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/databases/ncbi/_genesyn.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/databases/ncbi/_typing.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/databases/ncbi/data/gi/escherichia_coli_gene_info.tsv.gz +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/databases/ncbi/data/gi/homo_sapiens_gene_info.tsv.gz +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/databases/ncbi/data/gi/mus_musculus_gene_info.tsv.gz +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/databases/omnipath/__init__.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/databases/omnipath/_archive.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/databases/omnipath/_collectri.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/databases/omnipath/_dorothea.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/py.typed +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/sctools/__init__.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/sctools/_dependencies.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/sctools/_metadata.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/sctools/_stats.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/sctools/_typing.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/sctools/_validation.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/sctools/datasets/__init__.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/sctools/datasets/_metadata.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/sctools/datasets/_nestorowa.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/sctools/datasets/_pbmc3k.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/sctools/plotting/__init__.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/sctools/plotting/_colors.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/sctools/plotting/_figure.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/sctools/plotting/_typing.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/sctools/preprocessing/__init__.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/sctools/preprocessing/_classification.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/sctools/preprocessing/_duplicates.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/sctools/preprocessing/_filter.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/sctools/preprocessing/_genename.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/sctools/preprocessing/_simple.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/sctools/preprocessing/_transfer.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/sctools/tools/__init__.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/sctools/tools/_binarize.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/sctools/tools/_classification.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/sctools/tools/_clustering.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/sctools/tools/_conversion.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/sctools/tools/_embedding.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/sctools/tools/_graph.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/sctools/tools/_markers.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/sctools/tools/_maths.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/sctools/tools/_regress.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/sctools/tools/_utils.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/src/bonesistools/sctools/tools/_write.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/tests/.placeholder +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/tests/__init__.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/tests/golden/LICENSE.txt +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/tests/golden/__init__.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/tests/golden/expected/hvg_loess.npz +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/tests/golden/expected/neighbors.npz +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/tests/golden/expected/pca.npz +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/tests/golden/expected/qc.npz +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/tests/golden/generate_expected.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/tests/golden/pbmc3k.h5ad +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/tests/golden/test_pbmc3k.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/tests/regression/__init__.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/tests/regression/bpy/conftest.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/tests/regression/bpy/test_aggregated_influence_graph.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/tests/regression/bpy/test_boolean_network.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/tests/regression/bpy/test_boolean_network_ensemble.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/tests/regression/bpy/test_hypercube.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/tests/regression/bpy/test_hypercube_collection.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/tests/regression/bpy/test_influence_graph.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/tests/regression/bpy/test_influence_graph_distances.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/tests/regression/bpy/test_influence_graph_parser.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/tests/regression/bpy/test_influence_graph_scoring.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/tests/regression/bpy/test_partial_boolean.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/tests/regression/bpy/test_plotting_styles.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/tests/regression/dbs/test_hcop.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/tests/regression/dbs/test_ncbi.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/tests/regression/dbs/test_omnipath.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/tests/regression/sct/__init__.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/tests/regression/sct/conftest.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/tests/regression/sct/plotting/test_barplot.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/tests/regression/sct/plotting/test_colors.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/tests/regression/sct/plotting/test_density.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/tests/regression/sct/plotting/test_distribution.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/tests/regression/sct/plotting/test_figure.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/tests/regression/sct/plotting/test_graph.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/tests/regression/sct/plotting/test_scatterplot.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/tests/regression/sct/preprocessing/test_classification.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/tests/regression/sct/preprocessing/test_duplicates.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/tests/regression/sct/preprocessing/test_genename.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/tests/regression/sct/preprocessing/test_transfer_obs.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/tests/regression/sct/preprocessing/test_transform.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/tests/regression/sct/test_typing.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/tests/regression/sct/tools/test_binarize.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/tests/regression/sct/tools/test_clustering.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/tests/regression/sct/tools/test_conversion.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/tests/regression/sct/tools/test_embedding.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/tests/regression/sct/tools/test_knnsc.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/tests/regression/sct/tools/test_markers.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/tests/regression/sct/tools/test_maths.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/tests/regression/sct/tools/test_paga.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/tests/regression/sct/tools/test_regress.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/tests/regression/sct/tools/test_stats.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/tests/regression/sct/tools/test_utils.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/tests/regression/sct/tools/test_write.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/tests/regression/sct/toy_data.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/tests/regression/test_validation.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/tests/reproducibility/__init__.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/tests/reproducibility/dorothea_current_mouse_A.sha256 +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/tests/reproducibility/dorothea_legacy_mouse.sha256 +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/tests/reproducibility/test_reproducibility_omnipath.py +0 -0
- {bonesistools-1.2.8 → bonesistools-1.2.9}/tests/reproducibility/test_reproducibility_stats.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: bonesistools
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.9
|
|
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.2.
|
|
8
|
+
version = "1.2.9"
|
|
9
9
|
license = "CECILL-2.1"
|
|
10
10
|
credits = ["BNeDiction", "PEPR Santé Numérique 2030"]
|
|
11
11
|
authors = [
|
|
@@ -32,6 +32,8 @@ _GEO_FTP_BASE = "https://ftp.ncbi.nlm.nih.gov/geo"
|
|
|
32
32
|
_GSM_PATTERN = re.compile(r"^GSM[0-9]+$")
|
|
33
33
|
_DOWNLOAD_CHUNK_SIZE = 1024 * 1024
|
|
34
34
|
_DOWNLOAD_HEADERS = {"User-Agent": "bonesistools"}
|
|
35
|
+
_DOWNLOAD_LABEL_WIDTH = len("barcodes.tsv.gz")
|
|
36
|
+
_DOWNLOAD_SPEED_WIDTH = len("999.99K/s")
|
|
35
37
|
_SUPPLEMENTARY_SUFFIXES = (
|
|
36
38
|
"_matrix.mtx.gz",
|
|
37
39
|
"_barcodes.tsv.gz",
|
|
@@ -316,10 +318,12 @@ def _print_download_progress(
|
|
|
316
318
|
) -> None:
|
|
317
319
|
|
|
318
320
|
speed = downloaded / elapsed if elapsed > 0 else 0
|
|
321
|
+
label = _format_download_label(filename)
|
|
322
|
+
speed_label = f"{_format_bytes(speed)}/s"
|
|
319
323
|
if total is None or total == 0:
|
|
320
324
|
print(
|
|
321
|
-
f"\
|
|
322
|
-
f"{
|
|
325
|
+
f"\r{label} {_format_bytes(downloaded):>8} "
|
|
326
|
+
f"{speed_label:>{_DOWNLOAD_SPEED_WIDTH}}",
|
|
323
327
|
end="",
|
|
324
328
|
file=file,
|
|
325
329
|
flush=True,
|
|
@@ -334,8 +338,8 @@ def _print_download_progress(
|
|
|
334
338
|
else:
|
|
335
339
|
bar = "=" * filled + ">" + "." * max(0, width - filled - 1)
|
|
336
340
|
print(
|
|
337
|
-
f"\
|
|
338
|
-
f"{_format_bytes(downloaded):>8} {
|
|
341
|
+
f"\r{label} {percent:3d}%[{bar}] "
|
|
342
|
+
f"{_format_bytes(downloaded):>8} {speed_label:>{_DOWNLOAD_SPEED_WIDTH}} "
|
|
339
343
|
f"in {_format_duration(elapsed)}",
|
|
340
344
|
end="",
|
|
341
345
|
file=file,
|
|
@@ -343,6 +347,11 @@ def _print_download_progress(
|
|
|
343
347
|
)
|
|
344
348
|
|
|
345
349
|
|
|
350
|
+
def _format_download_label(filename: str) -> str:
|
|
351
|
+
|
|
352
|
+
return f"downloading {filename:<{_DOWNLOAD_LABEL_WIDTH}}"
|
|
353
|
+
|
|
354
|
+
|
|
346
355
|
def _format_bytes(size: float) -> str:
|
|
347
356
|
|
|
348
357
|
units = ("B", "K", "M", "G", "T")
|
|
@@ -354,7 +363,7 @@ def _format_bytes(size: float) -> str:
|
|
|
354
363
|
return f"{value:.2f}{unit}"
|
|
355
364
|
value /= 1024
|
|
356
365
|
|
|
357
|
-
return f"{value:.2f}T"
|
|
366
|
+
return f"{value:.2f}T" # pragma: no cover - defensive fallback
|
|
358
367
|
|
|
359
368
|
|
|
360
369
|
def _format_duration(seconds: float) -> str:
|
|
@@ -421,7 +430,11 @@ def _read_10x_mtx(
|
|
|
421
430
|
feature_path: Path,
|
|
422
431
|
) -> AnnData:
|
|
423
432
|
|
|
424
|
-
|
|
433
|
+
try:
|
|
434
|
+
matrix = scipy.io.mmread(str(matrix_path), spmatrix=True)
|
|
435
|
+
except TypeError:
|
|
436
|
+
matrix = scipy.io.mmread(str(matrix_path))
|
|
437
|
+
counts = sparse.csr_matrix(matrix)
|
|
425
438
|
obs_names = pd.Index(
|
|
426
439
|
_read_table(barcodes_path).iloc[:, 0].astype(str),
|
|
427
440
|
name=None,
|
|
@@ -9,7 +9,7 @@ from __future__ import annotations
|
|
|
9
9
|
import os
|
|
10
10
|
import shutil
|
|
11
11
|
from pathlib import Path
|
|
12
|
-
from typing import Callable, Dict, List
|
|
12
|
+
from typing import Any, Callable, Dict, Iterable, List, Optional
|
|
13
13
|
|
|
14
14
|
import pandas as pd
|
|
15
15
|
from anndata import AnnData
|
|
@@ -25,6 +25,8 @@ _DATASET_LOADERS: Dict[str, _DatasetLoader] = {
|
|
|
25
25
|
"nestorowa": _load_nestorowa,
|
|
26
26
|
"pbmc3k": _load_pbmc3k,
|
|
27
27
|
}
|
|
28
|
+
_OBSERVATION_COUNT_FIELDS = ("cells", "barcodes", "observations")
|
|
29
|
+
_FEATURE_COUNT_FIELDS = ("genes", "peaks")
|
|
28
30
|
|
|
29
31
|
|
|
30
32
|
def load(
|
|
@@ -58,11 +60,13 @@ def load(
|
|
|
58
60
|
dataset_name = _as_dataset_name(name)
|
|
59
61
|
quiet = _as_boolean(quiet, "quiet")
|
|
60
62
|
loader = _DATASET_LOADERS[dataset_name]
|
|
61
|
-
|
|
62
|
-
return loader(
|
|
63
|
+
adata = loader(
|
|
63
64
|
_dataset_cache_dir(dataset_name),
|
|
64
65
|
quiet,
|
|
65
66
|
)
|
|
67
|
+
_validate_dataset_shape(dataset_name, adata)
|
|
68
|
+
|
|
69
|
+
return adata
|
|
66
70
|
|
|
67
71
|
|
|
68
72
|
def info(name: str) -> Dict[str, object]:
|
|
@@ -159,6 +163,84 @@ def _as_dataset_name(name: str) -> str:
|
|
|
159
163
|
return dataset_name
|
|
160
164
|
|
|
161
165
|
|
|
166
|
+
def _validate_dataset_shape(
|
|
167
|
+
name: str,
|
|
168
|
+
adata: AnnData,
|
|
169
|
+
) -> None:
|
|
170
|
+
|
|
171
|
+
metadata = _DATASETS[name]
|
|
172
|
+
expected_observations = _expected_count(
|
|
173
|
+
metadata,
|
|
174
|
+
_OBSERVATION_COUNT_FIELDS,
|
|
175
|
+
)
|
|
176
|
+
expected_features = _expected_feature_count(metadata)
|
|
177
|
+
errors = []
|
|
178
|
+
if expected_observations is not None and adata.n_obs != expected_observations:
|
|
179
|
+
errors.append(
|
|
180
|
+
f"expected {expected_observations} observations but found "
|
|
181
|
+
f"{adata.n_obs}"
|
|
182
|
+
)
|
|
183
|
+
if expected_features is not None and adata.n_vars != expected_features:
|
|
184
|
+
errors.append(
|
|
185
|
+
f"expected {expected_features} features but found {adata.n_vars}"
|
|
186
|
+
)
|
|
187
|
+
if len(errors) == 0:
|
|
188
|
+
return
|
|
189
|
+
|
|
190
|
+
details = "; ".join(errors)
|
|
191
|
+
raise ValueError(
|
|
192
|
+
f"invalid cached dataset {name!r}: {details}. "
|
|
193
|
+
f"Clear cached files with bt.sct.datasets.clear({name!r}) and retry."
|
|
194
|
+
)
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
def _expected_count(
|
|
198
|
+
metadata: Dict[str, Any],
|
|
199
|
+
fields: Iterable[str],
|
|
200
|
+
) -> Optional[int]:
|
|
201
|
+
|
|
202
|
+
for field in fields:
|
|
203
|
+
if field in metadata:
|
|
204
|
+
return _metadata_count(metadata[field], field)
|
|
205
|
+
|
|
206
|
+
return None
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
def _expected_feature_count(metadata: Dict[str, Any]) -> Optional[int]:
|
|
210
|
+
|
|
211
|
+
if "features" in metadata:
|
|
212
|
+
return _metadata_count(metadata["features"], "features")
|
|
213
|
+
|
|
214
|
+
counts = [
|
|
215
|
+
_metadata_count(metadata[field], field)
|
|
216
|
+
for field in _FEATURE_COUNT_FIELDS
|
|
217
|
+
if field in metadata
|
|
218
|
+
]
|
|
219
|
+
if len(counts) == 0:
|
|
220
|
+
return None
|
|
221
|
+
|
|
222
|
+
return sum(counts)
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
def _metadata_count(
|
|
226
|
+
value: object,
|
|
227
|
+
field: str,
|
|
228
|
+
) -> int:
|
|
229
|
+
|
|
230
|
+
if not isinstance(value, int) or isinstance(value, bool):
|
|
231
|
+
raise TypeError(
|
|
232
|
+
f"invalid dataset metadata for '{field}': expected {int} "
|
|
233
|
+
f"but received {type(value)}"
|
|
234
|
+
)
|
|
235
|
+
if value < 0:
|
|
236
|
+
raise ValueError(
|
|
237
|
+
f"invalid dataset metadata for '{field}': expected non-negative "
|
|
238
|
+
f"value but received {value!r}"
|
|
239
|
+
)
|
|
240
|
+
|
|
241
|
+
return value
|
|
242
|
+
|
|
243
|
+
|
|
162
244
|
def _dataset_cache_root() -> Path:
|
|
163
245
|
|
|
164
246
|
root = Path(os.environ.get("XDG_CACHE_HOME", Path.home() / ".cache"))
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"cells": 1656,
|
|
8
8
|
"genes": 46078,
|
|
9
9
|
"source": "NCBI GEO (GSE81682)",
|
|
10
|
-
"license": "
|
|
10
|
+
"license": "Not specified",
|
|
11
11
|
"url": "https://www.ncbi.nlm.nih.gov/geo/query/acc.cgi?acc=GSE81682",
|
|
12
12
|
"citation": "Nestorowa et al. (2016). A single-cell resolution map of mouse hematopoietic stem and progenitor cell differentiation. Blood, 128(8), e20-e31."
|
|
13
13
|
},
|
|
@@ -30,12 +30,13 @@ from .._typing import ScData, anndata_or_mudata_checker
|
|
|
30
30
|
from ._colors import QUALITATIVE_COLORS, generate_colormap
|
|
31
31
|
from ._utils import (
|
|
32
32
|
_resolve_legend_argument,
|
|
33
|
+
apply_legend,
|
|
33
34
|
colormap_colors,
|
|
34
35
|
colors_from_uns,
|
|
35
|
-
figure_from_axes,
|
|
36
36
|
qualitative_color_values,
|
|
37
|
+
save_figure,
|
|
37
38
|
set_axis_label,
|
|
38
|
-
|
|
39
|
+
set_title,
|
|
39
40
|
)
|
|
40
41
|
|
|
41
42
|
Colors = Union[
|
|
@@ -48,94 +49,6 @@ Colors = Union[
|
|
|
48
49
|
Orientation = Literal["vertical", "horizontal"]
|
|
49
50
|
|
|
50
51
|
|
|
51
|
-
def __ordered_values(
|
|
52
|
-
series: pd.Series,
|
|
53
|
-
order: Optional[Sequence[object]],
|
|
54
|
-
) -> Sequence[object]:
|
|
55
|
-
|
|
56
|
-
if order is not None:
|
|
57
|
-
return list(order)
|
|
58
|
-
|
|
59
|
-
if isinstance(series.dtype, pd.CategoricalDtype):
|
|
60
|
-
return list(series.cat.categories)
|
|
61
|
-
|
|
62
|
-
return list(pd.unique(series.dropna()))
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
def __index_from_values(values: Sequence[object], name: str) -> pd.Index:
|
|
66
|
-
|
|
67
|
-
return pd.Index(np.asarray(list(values), dtype=object), name=name)
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
def __normalize_colors(
|
|
71
|
-
colors: Optional[Colors],
|
|
72
|
-
values: Sequence[object],
|
|
73
|
-
scdata: ScData,
|
|
74
|
-
uns_key: str,
|
|
75
|
-
) -> Sequence[object]:
|
|
76
|
-
|
|
77
|
-
if colors is None:
|
|
78
|
-
colors = colors_from_uns(scdata, uns_key, values)
|
|
79
|
-
|
|
80
|
-
if colors is None:
|
|
81
|
-
colors = qualitative_color_values(
|
|
82
|
-
len(values),
|
|
83
|
-
QUALITATIVE_COLORS,
|
|
84
|
-
generate_colormap,
|
|
85
|
-
)
|
|
86
|
-
|
|
87
|
-
if isinstance(colors, ListedColormap):
|
|
88
|
-
colors = colormap_colors(colors)
|
|
89
|
-
|
|
90
|
-
if isinstance(colors, str):
|
|
91
|
-
colors = plt.get_cmap(colors)
|
|
92
|
-
|
|
93
|
-
if isinstance(colors, Colormap):
|
|
94
|
-
positions = np.linspace(0, 1, len(values))
|
|
95
|
-
return cast(Sequence[object], colors(positions))
|
|
96
|
-
|
|
97
|
-
if isinstance(colors, MappingABC):
|
|
98
|
-
missing = [value for value in values if value not in colors]
|
|
99
|
-
|
|
100
|
-
if missing:
|
|
101
|
-
raise KeyError(f"missing colors for values: {missing!r}")
|
|
102
|
-
|
|
103
|
-
return [colors[value] for value in values]
|
|
104
|
-
|
|
105
|
-
color_values = list(cast(Sequence[object], colors))
|
|
106
|
-
|
|
107
|
-
if len(color_values) < len(values):
|
|
108
|
-
raise ValueError(
|
|
109
|
-
f"invalid argument value for 'colors': "
|
|
110
|
-
f"expected at least {len(values)} colors but received {len(color_values)}"
|
|
111
|
-
)
|
|
112
|
-
|
|
113
|
-
return color_values[0 : len(values)]
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
def __apply_ticklabel_colors(
|
|
117
|
-
ax: Axes,
|
|
118
|
-
colors: Optional[Mapping[object, object]],
|
|
119
|
-
orientation: Orientation,
|
|
120
|
-
) -> None:
|
|
121
|
-
|
|
122
|
-
if colors is None:
|
|
123
|
-
return None
|
|
124
|
-
|
|
125
|
-
ticklabels = (
|
|
126
|
-
ax.get_xticklabels() if orientation == "vertical" else ax.get_yticklabels()
|
|
127
|
-
)
|
|
128
|
-
|
|
129
|
-
for ticklabel in ticklabels:
|
|
130
|
-
value = ticklabel.get_text()
|
|
131
|
-
|
|
132
|
-
if value in colors:
|
|
133
|
-
ticklabel.set_color(cast(Any, colors[value]))
|
|
134
|
-
ticklabel.set_fontweight("bold")
|
|
135
|
-
|
|
136
|
-
return None
|
|
137
|
-
|
|
138
|
-
|
|
139
52
|
@overload
|
|
140
53
|
def composition(
|
|
141
54
|
scdata: ScData,
|
|
@@ -317,12 +230,66 @@ def composition(
|
|
|
317
230
|
|
|
318
231
|
legend = _resolve_legend_argument(legend, kwargs)
|
|
319
232
|
|
|
233
|
+
table, groups, segments = __composition_table(
|
|
234
|
+
scdata,
|
|
235
|
+
obs=obs,
|
|
236
|
+
groupby=groupby,
|
|
237
|
+
obs_order=obs_order,
|
|
238
|
+
group_order=group_order,
|
|
239
|
+
dropna=dropna,
|
|
240
|
+
normalize=normalize,
|
|
241
|
+
)
|
|
242
|
+
color_values = __normalize_colors(colors, segments, scdata, obs)
|
|
243
|
+
fig, ax = __composition_figure(ax, kwargs)
|
|
244
|
+
|
|
245
|
+
bar_kwargs = kwargs["bar"] if "bar" in kwargs else {}
|
|
246
|
+
table.plot(
|
|
247
|
+
kind="bar" if orientation == "vertical" else "barh",
|
|
248
|
+
stacked=True,
|
|
249
|
+
width=width,
|
|
250
|
+
color=color_values,
|
|
251
|
+
ax=ax,
|
|
252
|
+
**bar_kwargs,
|
|
253
|
+
)
|
|
254
|
+
|
|
255
|
+
__set_composition_axes(
|
|
256
|
+
ax,
|
|
257
|
+
normalize=normalize,
|
|
258
|
+
percent=percent,
|
|
259
|
+
orientation=orientation,
|
|
260
|
+
xlabel=xlabel,
|
|
261
|
+
ylabel=ylabel,
|
|
262
|
+
kwargs=kwargs,
|
|
263
|
+
)
|
|
264
|
+
|
|
265
|
+
if group_colors is None:
|
|
266
|
+
group_colors = colors_from_uns(scdata, groupby, groups)
|
|
267
|
+
__apply_ticklabel_colors(ax, group_colors, orientation)
|
|
268
|
+
set_title(fig, ax, title)
|
|
269
|
+
apply_legend(ax, legend, remove=True)
|
|
270
|
+
|
|
271
|
+
if save_figure(fig, outfile):
|
|
272
|
+
return None
|
|
273
|
+
|
|
274
|
+
return fig, ax
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
def __composition_table(
|
|
278
|
+
scdata: ScData,
|
|
279
|
+
*,
|
|
280
|
+
obs: str,
|
|
281
|
+
groupby: str,
|
|
282
|
+
obs_order: Optional[Sequence[object]],
|
|
283
|
+
group_order: Optional[Sequence[object]],
|
|
284
|
+
dropna: bool,
|
|
285
|
+
normalize: bool,
|
|
286
|
+
) -> Tuple[pd.DataFrame, Sequence[object], Sequence[object]]:
|
|
287
|
+
|
|
320
288
|
data = scdata.obs[[groupby, obs]]
|
|
321
289
|
data = data.dropna() if dropna else data
|
|
322
290
|
|
|
323
291
|
groups = __ordered_values(scdata.obs[groupby], group_order)
|
|
324
292
|
segments = __ordered_values(scdata.obs[obs], obs_order)
|
|
325
|
-
|
|
326
293
|
counts = pd.crosstab(data[groupby], data[obs])
|
|
327
294
|
counts = counts.reindex(
|
|
328
295
|
index=__index_from_values(groups, groupby),
|
|
@@ -330,38 +297,43 @@ def composition(
|
|
|
330
297
|
fill_value=0,
|
|
331
298
|
)
|
|
332
299
|
|
|
333
|
-
if normalize:
|
|
334
|
-
|
|
335
|
-
empty_groups = list(totals[totals == 0].index)
|
|
300
|
+
if not normalize:
|
|
301
|
+
return counts, groups, segments
|
|
336
302
|
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
303
|
+
totals = counts.sum(axis=1)
|
|
304
|
+
empty_groups = list(totals[totals == 0].index)
|
|
305
|
+
if empty_groups:
|
|
306
|
+
raise ValueError(
|
|
307
|
+
f"cannot normalize composition for empty groups: {empty_groups!r}"
|
|
308
|
+
)
|
|
309
|
+
return counts.div(totals, axis=0), groups, segments
|
|
341
310
|
|
|
342
|
-
table = counts.div(totals, axis=0)
|
|
343
|
-
else:
|
|
344
|
-
table = counts
|
|
345
311
|
|
|
346
|
-
|
|
312
|
+
def __composition_figure(
|
|
313
|
+
ax: Optional[Axes],
|
|
314
|
+
kwargs: Mapping[str, Any],
|
|
315
|
+
) -> Tuple[Figure, Axes]:
|
|
347
316
|
|
|
348
|
-
if ax is None:
|
|
349
|
-
|
|
350
|
-
ax = fig.subplots()
|
|
351
|
-
fig.set_figheight(kwargs["figheight"] if "figheight" in kwargs else 3)
|
|
352
|
-
fig.set_figwidth(kwargs["figwidth"] if "figwidth" in kwargs else 6)
|
|
353
|
-
else:
|
|
354
|
-
fig = figure_from_axes(ax)
|
|
317
|
+
if ax is not None:
|
|
318
|
+
return cast(Figure, ax.figure), ax
|
|
355
319
|
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
320
|
+
fig = plt.figure()
|
|
321
|
+
ax = fig.subplots()
|
|
322
|
+
fig.set_figheight(kwargs["figheight"] if "figheight" in kwargs else 3)
|
|
323
|
+
fig.set_figwidth(kwargs["figwidth"] if "figwidth" in kwargs else 6)
|
|
324
|
+
return fig, ax
|
|
325
|
+
|
|
326
|
+
|
|
327
|
+
def __set_composition_axes(
|
|
328
|
+
ax: Axes,
|
|
329
|
+
*,
|
|
330
|
+
normalize: bool,
|
|
331
|
+
percent: bool,
|
|
332
|
+
orientation: Orientation,
|
|
333
|
+
xlabel: Optional[Union[str, Mapping[str, Any]]],
|
|
334
|
+
ylabel: Optional[Union[str, Mapping[str, Any]]],
|
|
335
|
+
kwargs: Mapping[str, Any],
|
|
336
|
+
) -> None:
|
|
365
337
|
|
|
366
338
|
set_axis_label(ax, "xlabel", xlabel)
|
|
367
339
|
set_axis_label(ax, "ylabel", ylabel)
|
|
@@ -396,36 +368,92 @@ def composition(
|
|
|
396
368
|
)
|
|
397
369
|
for ticklabel in ticklabels:
|
|
398
370
|
ticklabel.set_rotation(rotation)
|
|
371
|
+
return None
|
|
399
372
|
|
|
400
|
-
if group_colors is None:
|
|
401
|
-
group_colors = colors_from_uns(scdata, groupby, groups)
|
|
402
|
-
__apply_ticklabel_colors(ax, group_colors, orientation)
|
|
403
373
|
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
374
|
+
def __ordered_values(
|
|
375
|
+
series: pd.Series,
|
|
376
|
+
order: Optional[Sequence[object]],
|
|
377
|
+
) -> Sequence[object]:
|
|
378
|
+
|
|
379
|
+
if order is not None:
|
|
380
|
+
return list(order)
|
|
381
|
+
|
|
382
|
+
if isinstance(series.dtype, pd.CategoricalDtype):
|
|
383
|
+
return list(series.cat.categories)
|
|
384
|
+
|
|
385
|
+
return list(pd.unique(series.dropna()))
|
|
386
|
+
|
|
387
|
+
|
|
388
|
+
def __index_from_values(values: Sequence[object], name: str) -> pd.Index:
|
|
389
|
+
|
|
390
|
+
return pd.Index(np.asarray(list(values), dtype=object), name=name)
|
|
391
|
+
|
|
392
|
+
|
|
393
|
+
def __normalize_colors(
|
|
394
|
+
colors: Optional[Colors],
|
|
395
|
+
values: Sequence[object],
|
|
396
|
+
scdata: ScData,
|
|
397
|
+
uns_key: str,
|
|
398
|
+
) -> Sequence[object]:
|
|
399
|
+
|
|
400
|
+
if colors is None:
|
|
401
|
+
colors = colors_from_uns(scdata, uns_key, values)
|
|
402
|
+
|
|
403
|
+
if colors is None:
|
|
404
|
+
colors = qualitative_color_values(
|
|
405
|
+
len(values),
|
|
406
|
+
QUALITATIVE_COLORS,
|
|
407
|
+
generate_colormap,
|
|
408
|
+
)
|
|
409
|
+
|
|
410
|
+
if isinstance(colors, ListedColormap):
|
|
411
|
+
colors = colormap_colors(colors)
|
|
412
|
+
|
|
413
|
+
if isinstance(colors, str):
|
|
414
|
+
colors = plt.get_cmap(colors)
|
|
415
|
+
|
|
416
|
+
if isinstance(colors, Colormap):
|
|
417
|
+
positions = np.linspace(0, 1, len(values))
|
|
418
|
+
return cast(Sequence[object], colors(positions))
|
|
419
|
+
|
|
420
|
+
if isinstance(colors, MappingABC):
|
|
421
|
+
missing = [value for value in values if value not in colors]
|
|
422
|
+
|
|
423
|
+
if missing:
|
|
424
|
+
raise KeyError(f"missing colors for values: {missing!r}")
|
|
425
|
+
|
|
426
|
+
return [colors[value] for value in values]
|
|
427
|
+
|
|
428
|
+
color_values = list(cast(Sequence[object], colors))
|
|
429
|
+
|
|
430
|
+
if len(color_values) < len(values):
|
|
431
|
+
raise ValueError(
|
|
432
|
+
f"invalid argument value for 'colors': "
|
|
433
|
+
f"expected at least {len(values)} colors but received {len(color_values)}"
|
|
434
|
+
)
|
|
435
|
+
|
|
436
|
+
return color_values[0 : len(values)]
|
|
437
|
+
|
|
438
|
+
|
|
439
|
+
def __apply_ticklabel_colors(
|
|
440
|
+
ax: Axes,
|
|
441
|
+
colors: Optional[Mapping[object, object]],
|
|
442
|
+
orientation: Orientation,
|
|
443
|
+
) -> None:
|
|
444
|
+
|
|
445
|
+
if colors is None:
|
|
429
446
|
return None
|
|
430
447
|
|
|
431
|
-
|
|
448
|
+
ticklabels = (
|
|
449
|
+
ax.get_xticklabels() if orientation == "vertical" else ax.get_yticklabels()
|
|
450
|
+
)
|
|
451
|
+
|
|
452
|
+
for ticklabel in ticklabels:
|
|
453
|
+
value = ticklabel.get_text()
|
|
454
|
+
|
|
455
|
+
if value in colors:
|
|
456
|
+
ticklabel.set_color(cast(Any, colors[value]))
|
|
457
|
+
ticklabel.set_fontweight("bold")
|
|
458
|
+
|
|
459
|
+
return None
|