Skip to content

Commit 393a32e

Browse files
authored
Merge pull request #5 from AFM-analysis/fix_kvm_model_numpy_versions
Fix kvm model numpy version compatibility
2 parents 484e79e + 05e9e45 commit 393a32e

5 files changed

Lines changed: 81 additions & 3 deletions

File tree

.github/workflows/check.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,11 @@ jobs:
3030
- name: Lint with flake8
3131
run: |
3232
flake8 --exclude _version.py .
33+
- name: Test with pytest (numpy v1)
34+
run: |
35+
pip install numpy==1.26.4
36+
pytest tests
37+
- name: Test with pytest (numpy v2)
38+
run: |
39+
pip install numpy==2.4.6
40+
pytest tests

CHANGELOG

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1+
0.1.2
2+
- fix: KVM hertz model compatible with numpy version 1 and 2 (#1, #5)
13
0.1.1
2-
- ci: update deploy_pypi to use pypi's trusted publisher system
4+
- setup: set the built tool system
5+
- ci: update deploy_pypi to use pypi's trusted publisher system
36
- ci: add check and deploy_pypi github actions (#3, #4)
47
0.1.0
58
- feat: add KVM hertz model (#2)

nanite_community/models/model_hertz_corrected_viscoelasticity_KVM.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,10 @@ def helper_retract_fraction(tip_position, force, fraction_force):
255255
fraction = int(0.8 * len(force))
256256
max_force = np.max(force[:fraction])
257257
max_position = -1 * tip_position[0]
258-
fit_stop = int(np.argwhere(force < (max_force * fraction_force))[0])
258+
_mask = force < (max_force * fraction_force)
259+
if not np.any(_mask):
260+
raise ValueError("No force values below threshold")
261+
fit_stop = int(np.argmax(_mask))
259262
position_seg = tip_position[:fit_stop].copy()
260263
force_seg = force[:fit_stop].copy()
261264

pyproject.toml

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
[build-system]
2+
requires = ["setuptools>=80", "setuptools-scm>=8"]
3+
build-backend = "setuptools.build_meta"
4+
15
[project]
26
name = "nanite-community"
37
description = "Repository for storing nanite models"
@@ -10,7 +14,7 @@ readme = "README.md"
1014
license = {text = "MIT"}
1115
dependencies = [
1216
"lmfit>=1.3.2",
13-
"numpy==1.26.*",
17+
"numpy>=1.26",
1418
]
1519
dynamic = ["version"]
1620
keywords=[
@@ -27,7 +31,13 @@ classifiers=[
2731
]
2832

2933
[dependency-groups]
34+
test = ["pytest"]
3035
lint = ["flake8"]
3136
dev = [
37+
{include-group = "test"},
3238
{include-group = "lint"}
3339
]
40+
41+
[tool.setuptools_scm]
42+
write_to = "nanite_community/_version.py"
43+
version_scheme = "post-release"
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import numpy as np
2+
import pytest
3+
4+
5+
def old_helper_retract_fraction(tip_position, force, fraction_force):
6+
fraction = int(0.8 * len(force))
7+
max_force = np.max(force[:fraction])
8+
max_position = -1 * tip_position[0]
9+
fit_stop = int(np.argwhere(force < (max_force * fraction_force))[0])
10+
position_seg = tip_position[:fit_stop].copy()
11+
force_seg = force[:fit_stop].copy()
12+
return position_seg, force_seg, max_position, max_force
13+
14+
15+
def new_helper_retract_fraction(tip_position, force, fraction_force):
16+
"""Reference implementation using NumPy 1.x and 2.x compatible indexing."""
17+
fraction = int(0.8 * len(force))
18+
max_force = np.max(force[:fraction])
19+
max_position = -1 * tip_position[0]
20+
21+
# new part
22+
_mask = force < (max_force * fraction_force)
23+
if not np.any(_mask):
24+
raise ValueError("No force values below threshold")
25+
fit_stop = int(np.argmax(_mask))
26+
27+
position_seg = tip_position[:fit_stop].copy()
28+
force_seg = force[:fit_stop].copy()
29+
return position_seg, force_seg, max_position, max_force
30+
31+
32+
def test_helper_behavior_differs_between_numpy_1_and_2():
33+
"""Show that newest version works for both numpy 1 and 2"""
34+
tip_position = np.linspace(0.0, -9.0, 10)
35+
force = np.array([10.0, 9.0, 8.0, 6.0, 4.0, 3.0, 2.0, 1.0, 0.0, 0.0])
36+
fraction_force = 0.5 # threshold = 5.0 -> first below threshold at index 4
37+
38+
major = int(np.__version__.split(".", 1)[0])
39+
if major < 2:
40+
# both old and new KVM work for numpy version 1
41+
old = old_helper_retract_fraction(tip_position, force, fraction_force)
42+
new = new_helper_retract_fraction(tip_position, force, fraction_force)
43+
np.testing.assert_allclose(old[0], new[0])
44+
np.testing.assert_allclose(old[1], new[1])
45+
assert old[2] == new[2]
46+
assert old[3] == new[3]
47+
else:
48+
# old implementation creates errors on NumPy 2
49+
# ("only length-1 arrays..." / "only 0-d arrays...").
50+
with pytest.raises(TypeError):
51+
old_helper_retract_fraction(tip_position, force, fraction_force)
52+
# therefore we need the new implementation, which works
53+
# with numpy version 2
54+
new_helper_retract_fraction(tip_position, force, fraction_force)

0 commit comments

Comments
 (0)