From 1fd4c3f95e9bb703b76e12109d38b567de9b1d1b Mon Sep 17 00:00:00 2001 From: colganwi Date: Thu, 24 Oct 2024 15:36:07 -0400 Subject: [PATCH 1/4] added python 3.11 compatability --- .github/workflows/test.yml | 4 +- cassiopeia/plotting/utilities.py | 4 +- cassiopeia/solver/HybridSolver.py | 1 - conftest.py | 18 +++-- pyproject.toml | 20 ++--- test/plotting_tests/local_3d_test.py | 8 ++ .../clonal_spatial_simulator_test.py | 5 ++ .../solver_tests/sharedmutationjoiner_test.py | 73 ------------------- 8 files changed, 41 insertions(+), 92 deletions(-) mode change 100644 => 100755 pyproject.toml diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 1a387aee..e20462db 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -15,7 +15,7 @@ jobs: timeout-minutes: 20 strategy: matrix: - python-version: [3.8, 3.9] + python-version: [3.8, 3.9, 3.10, 3.11] steps: - uses: actions/checkout@v2 @@ -34,7 +34,7 @@ jobs: run: | pip install pytest-cov pip install codecov - pip install ".[spatial]" + pip install . - name: Test with pytest run: | pytest -vv test/ --cov-report=xml --cov=cassiopeia diff --git a/cassiopeia/plotting/utilities.py b/cassiopeia/plotting/utilities.py index 34b95ccb..ab5830be 100644 --- a/cassiopeia/plotting/utilities.py +++ b/cassiopeia/plotting/utilities.py @@ -395,9 +395,9 @@ def get_random_indel_colors( if "none" in indel.lower(): indel2color[indel] = rgb_to_hsv((0.75, 0.75, 0.75)) elif indel == "NC": - indel2color[indel] = rgb_to_hsv((0, 0, 0)) + indel2color[indel] = rgb_to_hsv((0.0, 0.0, 0.0)) elif indel == "missing": - indel2color[indel] = rgb_to_hsv((1, 1, 1)) + indel2color[indel] = rgb_to_hsv((1.0, 1.0, 1.0)) else: # randomly pick a color family and then draw random colors # from that family diff --git a/cassiopeia/solver/HybridSolver.py b/cassiopeia/solver/HybridSolver.py index de9b0f21..f417b81b 100644 --- a/cassiopeia/solver/HybridSolver.py +++ b/cassiopeia/solver/HybridSolver.py @@ -13,7 +13,6 @@ import multiprocessing import networkx as nx import numpy as np -from numpy.lib.arraysetops import unique import pandas as pd from tqdm.auto import tqdm diff --git a/conftest.py b/conftest.py index e446d0a1..6d20926c 100644 --- a/conftest.py +++ b/conftest.py @@ -3,19 +3,27 @@ def pytest_addoption(parser): parser.addoption( - "--runslow", action="store_true", default=False, help="run slow tests" + "--runslow", action="store_true", default=False, help="run slow tests", + ) + parser.addoption( + "--runspatial", action="store_true", default=False, help="run spatial tests", ) def pytest_configure(config): config.addinivalue_line("markers", "slow: mark test as slow to run") + config.addinivalue_line("markers", "spatial: mark test as spatial to run") + def pytest_collection_modifyitems(config, items): - if config.getoption("--runslow"): - # --runslow given in cli: do not skip slow tests - return + run_slow = config.getoption("--runslow") + run_spatial = config.getoption("--runspatial") skip_slow = pytest.mark.skip(reason="need --runslow option to run") + skip_spatial = pytest.mark.skip(reason="need --runspatial option to run") + for item in items: - if "slow" in item.keywords: + if "slow" in item.keywords and not run_slow: item.add_marker(skip_slow) + if "spatial" in item.keywords and not run_spatial: + item.add_marker(skip_spatial) diff --git a/pyproject.toml b/pyproject.toml old mode 100644 new mode 100755 index d1d9fdc1..086a9491 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,9 +4,10 @@ classifiers = [ "Development Status :: 4 - Beta", "Intended Audience :: Science/Research", "Natural Language :: English", - "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", "Operating System :: MacOS :: MacOS X", "Operating System :: Microsoft :: Windows", "Operating System :: POSIX :: Linux", @@ -46,20 +47,19 @@ codecov = {version = ">=2.0.8", optional = true} cvxpy = "*" ete3 = ">=3.1.1" hits = "*" -importlib-metadata = {version = "^1.0", python = "<3.8"} ipython = {version = ">=7.20", optional = true, python = ">=3.7"} isort = {version = ">=5.7", optional = true} itolapi = "*" jupyter = {version = ">=1.0", optional = true} matplotlib = ">=2.2.2" -nbconvert = ">=5.4.0" -nbformat = ">=4.4.0" +nbconvert = {version = ">=5.4.0", optional = true} +nbformat = {version = ">=4.4.0", optional = true} nbsphinx = {version = "*", optional = true} nbsphinx-link = {version = "*", optional = true} -networkx = "==3.1" +networkx = ">=3.1" ngs-tools = ">=1.5.6" -numba = ">=0.51.0,<0.59.0" -numpy = ">=1.22" +numba = ">=0.51.0" +numpy = ">=2.0" opencv-python = {version = ">=4.5.4.60", optional = true} pandas = ">=1.1.4" parameterized = "*" @@ -75,7 +75,7 @@ pyvista = {version = "=0.41.0", optional = true} scanpydoc = {version = ">=0.5", optional = true} scikit-image = {version = ">=0.19.1", optional = true} scikit-learn = {version = ">=1.0.2", optional = true} -scipy = ">=1.2.0,<=1.11.4" +scipy = ">=1.2.0" sphinx = {version = ">=3.4", optional = true} sphinx-autodoc-typehints = {version = "*", optional = true} sphinx-gallery = {version = ">0.6", optional = true} @@ -93,7 +93,7 @@ script = "build.py" [build-system] build-backend = "poetry.core.masonry.api" -requires = ["poetry-core>=1.0.7", "Cython", "numpy>=1.19.5,<1.22", "setuptools", "pip>=22.0.0"] +requires = ["poetry-core>=1.0.7", "Cython", "numpy>=1.19.5", "setuptools", "pip>=22.0.0"] [tool.poetry.scripts] cassiopeia-preprocess = 'cassiopeia.preprocess.cassiopeia_preprocess:main' @@ -103,6 +103,8 @@ dev = ["black", "pytest", "flake8", "codecov", "jupyter", "pre-commit", "isort"] docs = [ "sphinx", "scanpydoc", + "nbconvert", + "nbformat", "nbsphinx", "nbsphinx-link", "ipython", diff --git a/test/plotting_tests/local_3d_test.py b/test/plotting_tests/local_3d_test.py index a8d36405..3d0559e7 100644 --- a/test/plotting_tests/local_3d_test.py +++ b/test/plotting_tests/local_3d_test.py @@ -1,5 +1,6 @@ import unittest from unittest import mock +import pytest import networkx as nx import numpy as np @@ -20,6 +21,7 @@ def setUp(self): self.labels = local_3d.labels_from_coordinates(self.tree) + @pytest.mark.spatial def test_interpolate_branch(self): parent = (0, 0, 0) child = (1, 1, 1) @@ -28,6 +30,7 @@ def test_interpolate_branch(self): local_3d.interpolate_branch(parent, child), ) + @pytest.mark.spatial def test_polyline_from_points(self): points = np.array( [ @@ -39,6 +42,7 @@ def test_polyline_from_points(self): poly = local_3d.polyline_from_points(points) np.testing.assert_array_equal(points, poly.points) + @pytest.mark.spatial def test_average_mixing(self): c1 = (0, 0, 0) c2 = (0.1, 0.2, 0.3) @@ -47,14 +51,17 @@ def test_average_mixing(self): (0.2, 0.3, 0.1), local_3d.average_mixing(c1, c2, c3) ) + @pytest.mark.spatial def test_highlight(self): c = (0.8, 0.2, 0.0) np.testing.assert_allclose((1.0, 0.25, 0.0), local_3d.highlight(c)) + @pytest.mark.spatial def test_lowlight(self): c = (0.8, 0.2, 0.0) np.testing.assert_allclose((0.3, 0.075, 0.0), local_3d.lowlight(c)) + @pytest.mark.spatial def test_labels_from_coordinates(self): # invalid shape with self.assertRaises(ValueError): @@ -82,6 +89,7 @@ def test_labels_from_coordinates(self): spatial_simulator.overlay_data(dense_tree) labels = local_3d.labels_from_coordinates(dense_tree, shape=(100, 100)) + @pytest.mark.spatial def test_Tree3D(self): # There isn't a good way to test this, other than making sure there # are no errors on initialization. diff --git a/test/simulator_tests/clonal_spatial_simulator_test.py b/test/simulator_tests/clonal_spatial_simulator_test.py index 1cb1000b..8d5876a7 100644 --- a/test/simulator_tests/clonal_spatial_simulator_test.py +++ b/test/simulator_tests/clonal_spatial_simulator_test.py @@ -1,4 +1,5 @@ import unittest +import pytest import networkx as nx import numpy as np @@ -53,6 +54,7 @@ def setUp(self): tree=topology, cell_meta=self.cell_meta ) + @pytest.mark.spatial def test_init(self): with self.assertRaises(DataSimulatorError): ClonalSpatialDataSimulator() @@ -69,6 +71,7 @@ def test_init(self): self.assertEqual(simulator.dim, 3) np.testing.assert_array_equal(np.ones((10, 10, 10), dtype=bool), simulator.space) + @pytest.mark.spatial def test_overlay_data(self): simulator = ClonalSpatialDataSimulator((100, 100)) simulator.overlay_data(self.basic_tree) @@ -107,6 +110,7 @@ def test_overlay_data(self): self.basic_tree.cell_meta, expected_cell_meta ) + @pytest.mark.spatial def test_overlay_data_with_space(self): simulator = ClonalSpatialDataSimulator(space=np.ones((100, 100), dtype=bool)) simulator.overlay_data(self.basic_tree) @@ -144,6 +148,7 @@ def test_overlay_data_with_space(self): self.basic_tree.cell_meta, expected_cell_meta ) + @pytest.mark.spatial def test_overlay_data_with_existing_cell_meta(self): simulator = ClonalSpatialDataSimulator((100, 100)) simulator.overlay_data(self.tree_with_cell_meta) diff --git a/test/solver_tests/sharedmutationjoiner_test.py b/test/solver_tests/sharedmutationjoiner_test.py index 232dae98..5a8a23f4 100755 --- a/test/solver_tests/sharedmutationjoiner_test.py +++ b/test/solver_tests/sharedmutationjoiner_test.py @@ -348,79 +348,6 @@ def test_basic_solver(self): nx.shortest_path_length(expected_tree, sample1, sample2), ) - def test_solver_no_numba(self): - self.smj_solver_no_numba.solve(self.basic_tree) - - # test that the dissimilarity map and character matrix were not altered - cm = pd.DataFrame.from_dict( - { - "a": [0, 1, 2], - "b": [1, 1, 2], - "c": [2, 2, 2], - "d": [1, 1, 1], - "e": [0, 0, 0], - }, - orient="index", - columns=["x1", "x2", "x3"], - ) - for i in self.basic_similarity_map.index: - for j in self.basic_similarity_map.columns: - self.assertEqual( - self.basic_similarity_map.loc[i, j], - self.basic_tree.get_dissimilarity_map().loc[i, j], - ) - for i in self.basic_tree.character_matrix.index: - for j in self.basic_tree.character_matrix.columns: - self.assertEqual( - cm.loc[i, j], self.basic_tree.character_matrix.loc[i, j] - ) - - # test leaves exist in tree - _leaves = self.basic_tree.leaves - - self.assertEqual(len(_leaves), self.basic_similarity_map.shape[0]) - for _leaf in _leaves: - self.assertIn(_leaf, self.basic_similarity_map.index.values) - - # test for expected number of edges - edges = list(self.basic_tree.edges) - self.assertEqual(len(edges), 8) - - # test relationships between samples - expected_tree = nx.DiGraph() - expected_tree.add_edges_from( - [ - ("5", "a"), - ("5", "b"), - ("6", "5"), - ("6", "c"), - ("7", "d"), - ("7", "e"), - ("8", "6"), - ("8", "7"), - ] - ) - - observed_tree = self.basic_tree.get_tree_topology() - triplets = itertools.combinations(["a", "b", "c", "d", "e"], 3) - for triplet in triplets: - - expected_triplet = find_triplet_structure(triplet, expected_tree) - observed_triplet = find_triplet_structure(triplet, observed_tree) - self.assertEqual(expected_triplet, observed_triplet) - - # compare tree distances - observed_tree = observed_tree.to_undirected() - expected_tree = expected_tree.to_undirected() - for i in range(len(_leaves)): - sample1 = _leaves[i] - for j in range(i + 1, len(_leaves)): - sample2 = _leaves[j] - self.assertEqual( - nx.shortest_path_length(observed_tree, sample1, sample2), - nx.shortest_path_length(expected_tree, sample1, sample2), - ) - def test_smj_solver_weights(self): self.smj_solver_modified_pp.solve(self.pp_tree_priors) observed_tree = self.pp_tree_priors.get_tree_topology() From 4c321e75127912a80f7c1631acb56366da170576 Mon Sep 17 00:00:00 2001 From: colganwi Date: Thu, 24 Oct 2024 15:41:32 -0400 Subject: [PATCH 2/4] fixed test.yml typo --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e20462db..da2106d0 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -15,7 +15,7 @@ jobs: timeout-minutes: 20 strategy: matrix: - python-version: [3.8, 3.9, 3.10, 3.11] + python-version: ["3.8", "3.9", "3.10", "3.11"] steps: - uses: actions/checkout@v2 From 4e7049087bf587eb951c6a33c491ad829972bf75 Mon Sep 17 00:00:00 2001 From: colganwi Date: Thu, 24 Oct 2024 16:03:04 -0400 Subject: [PATCH 3/4] bumped version to 2.1.0 --- .gitignore | 1 + pyproject.toml | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 3a857335..1e988d35 100755 --- a/.gitignore +++ b/.gitignore @@ -167,3 +167,4 @@ cassiopeia/tools/branch_length_estimator/_iid_exponential_bayesian.cpp docs/api/reference/** .vscode cassiopeia/config.ini +environment.yml diff --git a/pyproject.toml b/pyproject.toml index 086a9491..d5568094 100755 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,7 +21,7 @@ license = "MIT" name = "cassiopeia-lineage" readme = 'README.md' repository = "https://github.com/YosefLab/Cassiopeia" -version = "2.0.0" +version = "2.1.0" include = [ {path = "cassiopeia/preprocess/*.so", format = "wheel"}, @@ -47,7 +47,7 @@ codecov = {version = ">=2.0.8", optional = true} cvxpy = "*" ete3 = ">=3.1.1" hits = "*" -ipython = {version = ">=7.20", optional = true, python = ">=3.7"} +ipython = {version = ">=7.20", optional = true} isort = {version = ">=5.7", optional = true} itolapi = "*" jupyter = {version = ">=1.0", optional = true} @@ -59,7 +59,7 @@ nbsphinx-link = {version = "*", optional = true} networkx = ">=3.1" ngs-tools = ">=1.5.6" numba = ">=0.51.0" -numpy = ">=2.0" +numpy = ">=1.22, <3.0" opencv-python = {version = ">=4.5.4.60", optional = true} pandas = ">=1.1.4" parameterized = "*" From b6ab29a92e31210025cd9e95a586eae5361dda05 Mon Sep 17 00:00:00 2001 From: Matt Jones Date: Fri, 1 Nov 2024 15:00:32 -0700 Subject: [PATCH 4/4] moved around import statements --- test/plotting_tests/local_3d_test.py | 5 +---- test/simulator_tests/clonal_spatial_simulator_test.py | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/test/plotting_tests/local_3d_test.py b/test/plotting_tests/local_3d_test.py index 3d0559e7..40c14886 100644 --- a/test/plotting_tests/local_3d_test.py +++ b/test/plotting_tests/local_3d_test.py @@ -1,10 +1,7 @@ -import unittest -from unittest import mock import pytest +import unittest -import networkx as nx import numpy as np -import pandas as pd import cassiopeia as cas from cassiopeia.plotting import local_3d diff --git a/test/simulator_tests/clonal_spatial_simulator_test.py b/test/simulator_tests/clonal_spatial_simulator_test.py index 8d5876a7..faa997c7 100644 --- a/test/simulator_tests/clonal_spatial_simulator_test.py +++ b/test/simulator_tests/clonal_spatial_simulator_test.py @@ -1,5 +1,5 @@ -import unittest import pytest +import unittest import networkx as nx import numpy as np