Skip to content
This repository has been archived by the owner on Feb 26, 2025. It is now read-only.

Prepare for Python 3.13, fix issues with numpy>2 & matplotlib, #1131

Merged
merged 7 commits into from
Sep 27, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 1 addition & 1 deletion pylintrc
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
#R0903 - Too Few public methods
#W0511 - TODO in code
#R0401 - cyclic-import
disable=C0103,R0903,W0511,R0401,unspecified-encoding,consider-using-f-string
disable=C0103,R0903,W0511,R0401,unspecified-encoding,consider-using-f-string, too-many-positional-arguments

[FORMAT]
# Maximum number of characters on a single line.
Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ classifiers = [
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Topic :: Scientific/Engineering :: Bio-Informatics",
]
dependencies = [
Expand Down
10 changes: 5 additions & 5 deletions tests/apps/test_morph_stats.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,10 +212,9 @@ def test_extract_stats_scalar_feature():
# silence warning about approximating soma volume with a sphere
warnings.simplefilter("ignore", category=UserWarning)
res = ms.extract_stats(m, config)
assert res == {
'all': {'max_number_of_forking_points': 277},
'morphology': {'sum_soma_volume': 1424.4383771584492},
}

assert res["all"] == {'max_number_of_forking_points': 277}
assert_almost_equal(res["morphology"]["sum_soma_volume"], 1424.4383771584492, decimal=4)


def test_extract_stats__kwarg_modes_multiple_features():
Expand Down Expand Up @@ -493,7 +492,8 @@ def test_extract_dataframe_multiproc():
actual = ms.extract_dataframe(morphs, REF_CONFIG, n_workers=os.cpu_count() + 1)
# drop raw features as they require too much test data to mock
actual = actual.drop(columns='raw_section_branch_orders', level=1)
assert len(w) == 1, "Warning not emitted"
assert len(w) >= 1, "Warning not emitted"

assert_frame_equal(actual, expected, check_dtype=False)

with warnings.catch_warnings(record=True) as w:
Expand Down
4 changes: 2 additions & 2 deletions tests/core/test_section.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ def test_section_base_func():
assert section.id == 0
assert_array_equal(section.points, [[0, 0, 0, 1], [0, 5, 0, 1]])
assert_almost_equal(section.length, 5)
assert_almost_equal(section.area, 31.41592653589793)
assert_almost_equal(section.volume, 15.707963267948964)
assert_almost_equal(section.area, 31.4159, decimal=4)
assert_almost_equal(section.volume, 15.7079, decimal=4)

# __nonzero__
assert section
Expand Down
2 changes: 1 addition & 1 deletion tests/core/test_soma.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ def test_Soma_ThreePointCylinder():
assert 'SomaNeuromorphoThreePointCylinders' in str(sm)
assert isinstance(sm, soma.SomaNeuromorphoThreePointCylinders)
assert list(sm.center) == [0, 0, 0]
assert sm.radius == 44
assert_almost_equal(sm.radius, 44.0, decimal=5)


def test_Soma_ThreePointCylinder_invalid_radius():
Expand Down
18 changes: 16 additions & 2 deletions tests/features/test_get_features.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,9 @@ def test_max_radial_distance():

def test_section_tortuosity():
assert_allclose(
_stats(features.get('section_tortuosity', POP)), (1.0, 4.657, 440.408, 1.342), rtol=1e-3
_stats(features.get('section_tortuosity', POP)),
(1.0, 4.657, 440.408, 1.342),
rtol=1e-3,
)
assert_allclose(
_stats(features.get('section_tortuosity', POP, neurite_type=NeuriteType.all)),
Expand Down Expand Up @@ -326,6 +328,7 @@ def test_total_length():
assert_allclose(
features.get('total_length', POP, neurite_type=NeuriteType.axon),
[207.8797736031714, 207.81088341560977, 11767.156115224638],
rtol=1e-6,
)
assert_allclose(
features.get('total_length', POP, neurite_type=NeuriteType.apical_dendrite),
Expand Down Expand Up @@ -518,12 +521,14 @@ def test_neurite_volumes():
assert_allclose(
_stats(features.get('total_volume_per_neurite', POP, neurite_type=NeuriteType.axon)),
(276.58135508666612, 277.5357232437392, 830.85568094763551, 276.95189364921185),
rtol=1e-3,
)
assert_allclose(
_stats(
features.get('total_volume_per_neurite', POP, neurite_type=NeuriteType.apical_dendrite)
),
(271.94122143951864, 271.94122143951864, 271.94122143951864, 271.94122143951864),
rtol=1e-3,
)
assert_allclose(
_stats(
Expand Down Expand Up @@ -567,52 +572,61 @@ def test_neurite_density():
assert_allclose(
_stats(features.get('neurite_volume_density', POP)),
(6.1847539631150784e-06, 0.52464681266899216, 1.9767794901940539, 0.19767794901940539),
rtol=1e-6,
)
assert_allclose(
_stats(features.get('neurite_volume_density', POP, neurite_type=NeuriteType.all)),
(6.1847539631150784e-06, 0.52464681266899216, 1.9767794901940539, 0.19767794901940539),
rtol=1e-6,
)
assert_allclose(
_stats(features.get('neurite_volume_density', POP, neurite_type=NeuriteType.axon)),
(6.1847539631150784e-06, 0.26465213325053372, 0.5275513670655404, 0.1758504556885134),
1e-6,
rtol=1e-6,
)
assert_allclose(
_stats(
features.get('neurite_volume_density', POP, neurite_type=NeuriteType.apical_dendrite)
),
(0.43756606998299519, 0.43756606998299519, 0.43756606998299519, 0.43756606998299519),
rtol=1e-6,
)
assert_allclose(
_stats(
features.get('neurite_volume_density', POP, neurite_type=NeuriteType.basal_dendrite)
),
(0.00034968816544949771, 0.52464681266899216, 1.0116620531455183, 0.16861034219091972),
rtol=1e-6,
)

assert_allclose(
_stats(features.get('neurite_volume_density', NRN)),
(0.24068543213643726, 0.52464681266899216, 1.4657913638494682, 0.36644784096236704),
rtol=1e-6,
)
assert_allclose(
_stats(features.get('neurite_volume_density', NRN, neurite_type=NeuriteType.all)),
(0.24068543213643726, 0.52464681266899216, 1.4657913638494682, 0.36644784096236704),
rtol=1e-6,
)
assert_allclose(
_stats(features.get('neurite_volume_density', NRN, neurite_type=NeuriteType.axon)),
(0.26289304906104355, 0.26289304906104355, 0.26289304906104355, 0.26289304906104355),
rtol=1e-6,
)
assert_allclose(
_stats(
features.get('neurite_volume_density', NRN, neurite_type=NeuriteType.apical_dendrite)
),
(0.43756606998299519, 0.43756606998299519, 0.43756606998299519, 0.43756606998299519),
rtol=1e-6,
)
assert_allclose(
_stats(
features.get('neurite_volume_density', NRN, neurite_type=NeuriteType.basal_dendrite)
),
(0.24068543213643726, 0.52464681266899216, 0.76533224480542938, 0.38266612240271469),
rtol=1e-6,
)


Expand Down
9 changes: 5 additions & 4 deletions tests/features/test_morphology.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,8 @@ def test_soma_volume():


def test_soma_surface_area():
assert_allclose(morphology.soma_surface_area(SIMPLE), 12.566370614359172)
assert_allclose(morphology.soma_surface_area(NRN), 0.1075095256160432)
assert_allclose(morphology.soma_surface_area(SIMPLE), 12.566370614359172, rtol=1e-6)
assert_allclose(morphology.soma_surface_area(NRN), 0.1075095256160432, rtol=1e-6)


def test_soma_radius():
Expand All @@ -105,11 +105,11 @@ def surface(r0, r1, h):

basal_area = surface(1, 1, 5) + surface(1, 0, 5) + surface(1, 0, 6)
ret = morphology.total_area_per_neurite(SIMPLE, neurite_type=BASAL_DENDRITE)
assert_almost_equal(ret[0], basal_area)
assert_almost_equal(ret[0], basal_area, decimal=5)

axon_area = surface(1, 1, 4) + surface(1, 0, 5) + surface(1, 0, 6)
ret = morphology.total_area_per_neurite(SIMPLE, neurite_type=AXON)
assert_almost_equal(ret[0], axon_area)
assert_almost_equal(ret[0], axon_area, decimal=5)

ret = morphology.total_area_per_neurite(SIMPLE)
assert np.allclose(ret, [basal_area, axon_area])
Expand Down Expand Up @@ -143,6 +143,7 @@ def test_total_volume_per_neurite():
assert_allclose(
total_volumes,
[271.94122143951864, 281.24754646913954, 274.98039928781355, 276.73860261723024],
rtol=1e-6,
)


Expand Down
4 changes: 2 additions & 2 deletions tests/features/test_neurite.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ def test_neurite_volume_density():
0.24068543213643726,
0.26289304906104355,
]
assert_allclose(vol_density, ref_density)
assert_allclose(vol_density, ref_density, rtol=1e-6)


def test_neurite_volume_density_failed_convex_hull():
Expand Down Expand Up @@ -215,7 +215,7 @@ def test_segment_areas():
def test_segment_volumes():
expected = [[15.70796327, 5.23598776, 6.28318531], [12.56637061, 6.28318531, 5.23598776]]
result = [neurite.segment_volumes(s) for s in SIMPLE.neurites]
assert_allclose(result, expected)
assert_allclose(result, expected, rtol=1e-6)


def test_segment_midpoints():
Expand Down
11 changes: 10 additions & 1 deletion tests/view/test_matplotlib_impl.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,10 @@
import warnings
from io import StringIO
from pathlib import Path
from packaging.version import parse

import numpy as np
import matplotlib
from neurom import load_morphology
from neurom.core.types import NeuriteType
from neurom.view import matplotlib_utils, matplotlib_impl
Expand Down Expand Up @@ -112,7 +114,14 @@ def test_tree3d(get_fig_3d):
xy_bounds = ax.xy_dataLim.bounds
np.testing.assert_allclose(xy_bounds, (-5.0, 0.0, 11.0, 5.0))
zz_bounds = ax.zz_dataLim.bounds
np.testing.assert_allclose(zz_bounds, (0.0, 0.0, 1.0, 1.0))

# auto scaling of data limits was fixed for LineCollection3D
# in 3.9.1+ fixing the previously wrong bbox limits
# See: https://github.com/matplotlib/matplotlib/pull/28403
if parse(matplotlib.__version__) < parse("3.9.1"):
np.testing.assert_allclose(zz_bounds, (0.0, 0.0, 1.0, 1.0))
else:
np.testing.assert_allclose(zz_bounds, (0.0, 0.0, 0.0, 1.0))


def test_morph3d(get_fig_3d):
Expand Down
3 changes: 2 additions & 1 deletion tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ envlist =
coverage
tutorial
check-packaging
py{38,39,310,311,312}
py{38,39,310,311,312,313}

[testenv]
deps =
Expand Down Expand Up @@ -102,3 +102,4 @@ python =
3.10: py310, tutorial
3.11: py311, check-packaging
3.12: py312
3.13: py313
Loading