grainmorph 0.3.0__tar.gz → 0.3.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. {grainmorph-0.3.0/src/grainmorph.egg-info → grainmorph-0.3.1}/PKG-INFO +1 -1
  2. {grainmorph-0.3.0 → grainmorph-0.3.1}/pyproject.toml +1 -1
  3. grainmorph-0.3.1/src/grainmorph/wadell/discretize.py +59 -0
  4. {grainmorph-0.3.0 → grainmorph-0.3.1/src/grainmorph.egg-info}/PKG-INFO +1 -1
  5. {grainmorph-0.3.0 → grainmorph-0.3.1}/tests/test_discretize.py +6 -3
  6. grainmorph-0.3.0/src/grainmorph/wadell/discretize.py +0 -41
  7. {grainmorph-0.3.0 → grainmorph-0.3.1}/LICENSE +0 -0
  8. {grainmorph-0.3.0 → grainmorph-0.3.1}/README.md +0 -0
  9. {grainmorph-0.3.0 → grainmorph-0.3.1}/setup.cfg +0 -0
  10. {grainmorph-0.3.0 → grainmorph-0.3.1}/src/grainmorph/__init__.py +0 -0
  11. {grainmorph-0.3.0 → grainmorph-0.3.1}/src/grainmorph/analyzer.py +0 -0
  12. {grainmorph-0.3.0 → grainmorph-0.3.1}/src/grainmorph/mask.py +0 -0
  13. {grainmorph-0.3.0 → grainmorph-0.3.1}/src/grainmorph/metrics.py +0 -0
  14. {grainmorph-0.3.0 → grainmorph-0.3.1}/src/grainmorph/utils/__init__.py +0 -0
  15. {grainmorph-0.3.0 → grainmorph-0.3.1}/src/grainmorph/utils/particle.py +0 -0
  16. {grainmorph-0.3.0 → grainmorph-0.3.1}/src/grainmorph/utils/plot.py +0 -0
  17. {grainmorph-0.3.0 → grainmorph-0.3.1}/src/grainmorph/utils/shape.py +0 -0
  18. {grainmorph-0.3.0 → grainmorph-0.3.1}/src/grainmorph/wadell/__init__.py +0 -0
  19. {grainmorph-0.3.0 → grainmorph-0.3.1}/src/grainmorph/wadell/corner.py +0 -0
  20. {grainmorph-0.3.0 → grainmorph-0.3.1}/src/grainmorph/wadell/smoothing.py +0 -0
  21. {grainmorph-0.3.0 → grainmorph-0.3.1}/src/grainmorph.egg-info/SOURCES.txt +0 -0
  22. {grainmorph-0.3.0 → grainmorph-0.3.1}/src/grainmorph.egg-info/dependency_links.txt +0 -0
  23. {grainmorph-0.3.0 → grainmorph-0.3.1}/src/grainmorph.egg-info/requires.txt +0 -0
  24. {grainmorph-0.3.0 → grainmorph-0.3.1}/src/grainmorph.egg-info/top_level.txt +0 -0
  25. {grainmorph-0.3.0 → grainmorph-0.3.1}/tests/test_analyzer.py +0 -0
  26. {grainmorph-0.3.0 → grainmorph-0.3.1}/tests/test_corner.py +0 -0
  27. {grainmorph-0.3.0 → grainmorph-0.3.1}/tests/test_mask.py +0 -0
  28. {grainmorph-0.3.0 → grainmorph-0.3.1}/tests/test_metrics.py +0 -0
  29. {grainmorph-0.3.0 → grainmorph-0.3.1}/tests/test_particle.py +0 -0
  30. {grainmorph-0.3.0 → grainmorph-0.3.1}/tests/test_plot.py +0 -0
  31. {grainmorph-0.3.0 → grainmorph-0.3.1}/tests/test_shape.py +0 -0
  32. {grainmorph-0.3.0 → grainmorph-0.3.1}/tests/test_smoothing.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: grainmorph
3
- Version: 0.3.0
3
+ Version: 0.3.1
4
4
  Summary: Particle shape analysis and visualization library.
5
5
  Author: GrainMorph Contributors
6
6
  License-Expression: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "grainmorph"
7
- version = "0.3.0"
7
+ version = "0.3.1"
8
8
  authors = [
9
9
  { name = "GrainMorph Contributors" }
10
10
  ]
@@ -0,0 +1,59 @@
1
+ import math
2
+
3
+ import numpy as np
4
+
5
+
6
+ def discretize_boundary(boundary, max_dev_thresh):
7
+ num = len(boundary)
8
+ # Separate columns and plain floats keep each of the many short calls cheap.
9
+ x = np.append(boundary[:, 0], boundary[0, 0])
10
+ y = np.append(boundary[:, 1], boundary[0, 1])
11
+ xs = x.tolist()
12
+ ys = y.tolist()
13
+ keep = [0]
14
+
15
+ start, end = 0, num
16
+ while start < num:
17
+ dev, idx = find_max_deviation(
18
+ x[start : end + 1],
19
+ y[start : end + 1],
20
+ xs[start],
21
+ ys[start],
22
+ xs[end],
23
+ ys[end],
24
+ )
25
+ # A peak at either end would not shrink the segment.
26
+ while dev > max_dev_thresh and 0 < idx < end - start:
27
+ end = start + idx
28
+ dev, idx = find_max_deviation(
29
+ x[start : end + 1],
30
+ y[start : end + 1],
31
+ xs[start],
32
+ ys[start],
33
+ xs[end],
34
+ ys[end],
35
+ )
36
+
37
+ if end < num:
38
+ keep.append(end)
39
+ start, end = end, num
40
+
41
+ return boundary[keep]
42
+
43
+
44
+ def find_max_deviation(x, y, x0, y0, x1, y1):
45
+ dx = x1 - x0
46
+ dy = y0 - y1
47
+ chord_sq = dx * dx + dy * dy
48
+
49
+ if chord_sq < 1e-12:
50
+ dist_sq = np.square(x - x0) + np.square(y - y0)
51
+ idx = int(dist_sq.argmax())
52
+ return math.sqrt(float(dist_sq[idx])), idx
53
+
54
+ dist = dy * x
55
+ dist += dx * y
56
+ dist += y1 * x0 - y0 * x1
57
+ np.abs(dist, out=dist)
58
+ idx = int(dist.argmax())
59
+ return float(dist[idx]) / math.sqrt(chord_sq), idx
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: grainmorph
3
- Version: 0.3.0
3
+ Version: 0.3.1
4
4
  Summary: Particle shape analysis and visualization library.
5
5
  Author: GrainMorph Contributors
6
6
  License-Expression: MIT
@@ -28,13 +28,16 @@ def test_max_deviation_is_invariant_to_rigid_transforms(angle, offset):
28
28
  theta = np.deg2rad(angle)
29
29
  axes = np.array([[np.cos(theta), -np.sin(theta)], [np.sin(theta), np.cos(theta)]])
30
30
 
31
- deviation, idx = find_max_deviation(points @ axes.T + offset)
31
+ x, y = (points @ axes.T + offset).T
32
+
33
+ deviation, idx = find_max_deviation(x, y, x[0], y[0], x[-1], y[-1])
32
34
 
33
35
  assert deviation == pytest.approx(2.0)
34
36
  assert idx == 1
35
37
 
36
38
 
37
39
  def test_max_deviation_with_coincident_endpoints():
38
- points = np.array([[1.0, 2.0], [4.0, 6.0], [1.0, 2.0]])
40
+ x = np.array([1.0, 4.0, 1.0])
41
+ y = np.array([2.0, 6.0, 2.0])
39
42
 
40
- assert find_max_deviation(points) == (5.0, 1)
43
+ assert find_max_deviation(x, y, 1.0, 2.0, 1.0, 2.0) == (5.0, 1)
@@ -1,41 +0,0 @@
1
- import math
2
-
3
- import numpy as np
4
-
5
-
6
- def discretize_boundary(boundary, max_dev_thresh):
7
- num = len(boundary)
8
- closed = np.vstack([boundary, boundary[0]])
9
- keypoints = [boundary[0]]
10
-
11
- start, end = 0, num
12
- while start < num:
13
- dev, idx = find_max_deviation(closed[start : end + 1])
14
- # A peak at either end would not shrink the segment.
15
- while dev > max_dev_thresh and 0 < idx < end - start:
16
- end = start + idx
17
- dev, idx = find_max_deviation(closed[start : end + 1])
18
-
19
- if end < num:
20
- keypoints.append(closed[end])
21
- start, end = end, num
22
-
23
- return np.array(keypoints)
24
-
25
-
26
- def find_max_deviation(points):
27
- x, y = points.T
28
- x0, y0 = points[0].tolist()
29
- x1, y1 = points[-1].tolist()
30
- dx = x1 - x0
31
- dy = y0 - y1
32
- chord_sq = dx * dx + dy * dy
33
-
34
- if chord_sq < 1e-12:
35
- dist_sq = np.square(x - x0) + np.square(y - y0)
36
- idx = int(dist_sq.argmax())
37
- return math.sqrt(float(dist_sq[idx])), idx
38
-
39
- dist = np.abs(dy * x + dx * y + (y1 * x0 - y0 * x1))
40
- idx = int(dist.argmax())
41
- return float(dist[idx]) / math.sqrt(chord_sq), idx
File without changes
File without changes
File without changes