Skip to content

Commit

Permalink
Refactor graph tests
Browse files Browse the repository at this point in the history
- use pytest functions which can use fixtures
- use fixtures to reduce network roundtrips
- use parametrized fixture to control igraph usage
  - also splits igraph tests into 2
  • Loading branch information
clbarnes committed Jan 9, 2024
1 parent 647d688 commit 7016f8f
Show file tree
Hide file tree
Showing 3 changed files with 145 additions and 98 deletions.
63 changes: 63 additions & 0 deletions pymaid/tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import os
import pytest
import navis
from contextlib import contextmanager
import logging
import pymaid

logger = logging.getLogger(__name__)


@contextmanager
def igraph_context(use_igraph):
orig = navis.config.use_igraph
logger.debug(f"Setting navis.config.use_igraph = {use_igraph}")
navis.config.use_igraph = use_igraph
yield use_igraph
logger.debug(f"Resetting navis.config.use_igraph = {orig}")
navis.config.use_igraph = orig


@pytest.fixture(scope="session", params=[True, False])
def use_igraph(request):
with igraph_context(request.param) as use:
yield use


@pytest.fixture(scope="module")
def client():
return pymaid.CatmaidInstance(
os.environ.get("PYMAID_TEST_SERVER_URL", 'https://fafb.catmaid.virtualflybrain.org/'),
os.environ.get("PYMAID_TEST_TOKEN"),
os.environ.get("PYMAID_TEST_HTTP_USER"),
os.environ.get("PYMAID_TEST_HTTP_PW"),
make_global=True,
)


@pytest.fixture(scope="module")
def skids():
return [
int(s) for s in os.environ.get(
"PYMAID_TEST_SKIDS",
"16,1299740,4744251"
).split(",")
]


@pytest.fixture(scope="module")
def annotation_names():
return os.environ.get(
"PYMAID_TEST_ANNOTATIONS",
'Paper: Dolan and Belliart-Guérin et al. 2018,Paper: Wang et al 2020a'
).split(",")


@pytest.fixture(scope="module")
def volume_name():
return os.environ.get("PYMAID_TEST_VOLUME", "LH_R")


@pytest.fixture(scope="module")
def stack_id():
return int(os.environ.get("PYMAID_TEST_STACK_ID", 1))
81 changes: 81 additions & 0 deletions pymaid/tests/test_graph.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import pytest
import pymaid
import navis as ns
import numpy as np

SEED = 1991

@pytest.fixture(scope="module")
def neuron_list(client, skids):
return pymaid.get_neuron(skids[0:2], remote_instance=client)


@pytest.fixture(scope="module")
def neuron(neuron_list):
n = neuron_list[0]
return n.reroot(n.soma, inplace=False)

@pytest.fixture(scope="module")
def leaf_slab(neuron):
rng = np.random.default_rng(SEED)
leaf_id = neuron.nodes[neuron.nodes.type == 'end'].sample(
1, random_state=rng).iloc[0].node_id
slab_id = neuron.nodes[neuron.nodes.type == 'slab'].sample(
1, random_state=rng).iloc[0].node_id
return (leaf_id, slab_id)


def test_reroot(neuron_list, neuron, leaf_slab, use_igraph):
leaf_id, slab_id = leaf_slab
assert neuron.reroot(leaf_id, inplace=False) is not None
assert neuron_list.reroot(neuron_list.soma, inplace=False) is not None


def test_distal_to(neuron, leaf_slab, use_igraph):
leaf_id, slab_id = leaf_slab
assert ns.distal_to(neuron, leaf_id, neuron.root)
assert not ns.distal_to(neuron, neuron.root, leaf_id)


def test_distance(neuron, use_igraph):
leaf_id = neuron.nodes[neuron.nodes.type == 'end'].iloc[0].node_id

assert ns.dist_between(neuron, leaf_id, neuron.root) is not None
assert ns.dist_between(neuron, neuron.root, leaf_id) is not None


def test_find_bp(neuron, use_igraph):
assert ns.find_main_branchpoint(neuron, reroot_soma=False) is not None


def test_split_fragments(neuron, use_igraph):
assert ns.split_into_fragments(neuron, n=2, reroot_soma=False) is not None


def test_longest_neurite(neuron, use_igraph):
assert ns.longest_neurite(neuron, n=2, reroot_soma=False) is not None


def test_cut_neuron(neuron, leaf_slab, use_igraph):
leaf_id, slab_id = leaf_slab
dist, prox = ns.cut_skeleton(neuron, slab_id)
assert dist.nodes.shape != prox.nodes.shape

# Make sure dist and prox check out
assert ns.distal_to(neuron, dist.root, prox.root)


def test_subset(neuron, use_igraph):
assert isinstance(
ns.subset_neuron(neuron, neuron.segments[0]),
pymaid.CatmaidNeuron
)


def test_node_sorting(neuron, use_igraph):
result = ns.graph.node_label_sorting(neuron)
assert isinstance(result, np.ndarray)


def test_geodesic_matrix(neuron, use_igraph):
geo = ns.geodesic_matrix(neuron)
99 changes: 1 addition & 98 deletions pymaid/tests/test_pymaid.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import warnings
import os
import matplotlib as mpl
import pytest
#if os.environ.get('DISPLAY', '') == '':
# warnings.warn('No display found. Using template backend (nothing '
# 'will show).')
Expand Down Expand Up @@ -605,104 +606,6 @@ def test_guess_radius(self):
pymaid.CatmaidNeuron)


class TestGraphs(unittest.TestCase):
"""Test graph functions."""

def try_conditions(func):
"""Runs each test under various conditions and asserts that results
are always the same."""

def wrapper(self, *args, **kwargs):
ns.config.use_igraph = False
res1 = func(self, *args, **kwargs)
if igraph:
ns.config.use_igraph = True
res2 = func(self, *args, **kwargs)
self.assertEqual(res1, res2)
return res1
return wrapper

def setUp(self):
self.rm = pymaid.CatmaidInstance(server=config_test.server_url,
http_user=config_test.http_user,
http_password=config_test.http_pw,
api_token=config_test.token,
make_global=True)

self.nl = pymaid.get_neuron(config_test.test_skids[0:2],
remote_instance=self.rm)

self.n = self.nl[0]
self.n.reroot(self.n.soma)

# Get some random leaf node
self.leaf_id = self.n.nodes[self.n.nodes.type == 'end'].sample(
1).iloc[0].node_id
self.slab_id = self.n.nodes[self.n.nodes.type == 'slab'].sample(
1).iloc[0].node_id

@try_conditions
def test_reroot(self):
self.assertIsNotNone(self.n.reroot(self.leaf_id, inplace=False))
self.assertIsNotNone(self.nl.reroot(self.nl.soma, inplace=False))

@try_conditions
def test_distal_to(self):
self.assertTrue(ns.distal_to(self.n, self.leaf_id, self.n.root))
self.assertFalse(ns.distal_to(self.n, self.n.root, self.leaf_id))

@try_conditions
def test_distance(self):
leaf_id = self.n.nodes[self.n.nodes.type == 'end'].iloc[0].node_id

self.assertIsNotNone(ns.dist_between(self.n,
leaf_id,
self.n.root))
self.assertIsNotNone(ns.dist_between(self.n,
self.n.root,
leaf_id))

@try_conditions
def test_find_bp(self):
self.assertIsNotNone(ns.find_main_branchpoint(self.n,
reroot_soma=False))

@try_conditions
def test_split_fragments(self):
self.assertIsNotNone(ns.split_into_fragments(self.n,
n=2,
reroot_soma=False))

@try_conditions
def test_longest_neurite(self):
self.assertIsNotNone(ns.longest_neurite(self.n,
n=2,
reroot_soma=False))

@try_conditions
def test_cut_neuron(self):
dist, prox = ns.cut_skeleton(self.n, self.slab_id)
self.assertNotEqual(dist.nodes.shape, prox.nodes.shape)

# Make sure dist and prox check out
self.assertTrue(ns.distal_to(self.n, dist.root, prox.root))

@try_conditions
def test_subset(self):
self.assertIsInstance(ns.subset_neuron(self.n,
self.n.segments[0]),
pymaid.CatmaidNeuron)

@try_conditions
def test_node_sorting(self):
self.assertIsInstance(ns.graph.node_label_sorting(self.n),
list)

@try_conditions
def test_geodesic_matrix(self):
geo = ns.geodesic_matrix(self.n)


class TestConnectivity(unittest.TestCase):
"""Test connectivity-related functions."""

Expand Down

0 comments on commit 7016f8f

Please sign in to comment.