Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added python 3.10 and 3.11 support #251

Merged
merged 4 commits into from
Nov 1, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -167,3 +167,4 @@ cassiopeia/tools/branch_length_estimator/_iid_exponential_bayesian.cpp
docs/api/reference/**
.vscode
cassiopeia/config.ini
environment.yml
4 changes: 2 additions & 2 deletions cassiopeia/plotting/utilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 0 additions & 1 deletion cassiopeia/solver/HybridSolver.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
18 changes: 13 additions & 5 deletions conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
24 changes: 13 additions & 11 deletions pyproject.toml
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -20,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"},
Expand All @@ -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"}
ipython = {version = ">=7.20", optional = true}
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 = ">=1.22, <3.0"
opencv-python = {version = ">=4.5.4.60", optional = true}
pandas = ">=1.1.4"
parameterized = "*"
Expand All @@ -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}
Expand All @@ -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'
Expand All @@ -103,6 +103,8 @@ dev = ["black", "pytest", "flake8", "codecov", "jupyter", "pre-commit", "isort"]
docs = [
"sphinx",
"scanpydoc",
"nbconvert",
"nbformat",
"nbsphinx",
"nbsphinx-link",
"ipython",
Expand Down
8 changes: 8 additions & 0 deletions test/plotting_tests/local_3d_test.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import unittest
from unittest import mock
import pytest

import networkx as nx
import numpy as np
Expand All @@ -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)
Expand All @@ -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(
[
Expand All @@ -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)
Expand All @@ -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):
Expand Down Expand Up @@ -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.
Expand Down
5 changes: 5 additions & 0 deletions test/simulator_tests/clonal_spatial_simulator_test.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import unittest
import pytest

import networkx as nx
import numpy as np
Expand Down Expand Up @@ -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()
Expand All @@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down
73 changes: 0 additions & 73 deletions test/solver_tests/sharedmutationjoiner_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
Loading