Simple-Track 2.2.0__tar.gz → 2.2.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.
- {simple_track-2.2.0 → simple_track-2.2.1}/PKG-INFO +1 -1
- {simple_track-2.2.0 → simple_track-2.2.1}/pyproject.toml +2 -2
- {simple_track-2.2.0 → simple_track-2.2.1}/src/Simple_Track.egg-info/PKG-INFO +1 -1
- {simple_track-2.2.0 → simple_track-2.2.1}/src/simpletrack/feature.py +5 -4
- {simple_track-2.2.0 → simple_track-2.2.1}/src/simpletrack/frame_tracker.py +7 -7
- {simple_track-2.2.0 → simple_track-2.2.1}/src/simpletrack/track.py +9 -2
- {simple_track-2.2.0 → simple_track-2.2.1}/tests/test_flow_solver.py +5 -2
- {simple_track-2.2.0 → simple_track-2.2.1}/tests/test_frame_tracker.py +2 -1
- {simple_track-2.2.0 → simple_track-2.2.1}/LICENSE +0 -0
- {simple_track-2.2.0 → simple_track-2.2.1}/README.md +0 -0
- {simple_track-2.2.0 → simple_track-2.2.1}/setup.cfg +0 -0
- {simple_track-2.2.0 → simple_track-2.2.1}/src/Simple_Track.egg-info/SOURCES.txt +0 -0
- {simple_track-2.2.0 → simple_track-2.2.1}/src/Simple_Track.egg-info/dependency_links.txt +0 -0
- {simple_track-2.2.0 → simple_track-2.2.1}/src/Simple_Track.egg-info/entry_points.txt +0 -0
- {simple_track-2.2.0 → simple_track-2.2.1}/src/Simple_Track.egg-info/requires.txt +0 -0
- {simple_track-2.2.0 → simple_track-2.2.1}/src/Simple_Track.egg-info/top_level.txt +0 -0
- {simple_track-2.2.0 → simple_track-2.2.1}/src/run_simple_track.py +0 -0
- {simple_track-2.2.0 → simple_track-2.2.1}/src/simpletrack/__init__.py +0 -0
- {simple_track-2.2.0 → simple_track-2.2.1}/src/simpletrack/exceptions.py +0 -0
- {simple_track-2.2.0 → simple_track-2.2.1}/src/simpletrack/flow_solver.py +0 -0
- {simple_track-2.2.0 → simple_track-2.2.1}/src/simpletrack/frame.py +0 -0
- {simple_track-2.2.0 → simple_track-2.2.1}/src/simpletrack/frame_output.py +0 -0
- {simple_track-2.2.0 → simple_track-2.2.1}/src/simpletrack/load.py +0 -0
- {simple_track-2.2.0 → simple_track-2.2.1}/src/simpletrack/utils.py +0 -0
- {simple_track-2.2.0 → simple_track-2.2.1}/tests/test_cli.py +0 -0
- {simple_track-2.2.0 → simple_track-2.2.1}/tests/test_feature.py +0 -0
- {simple_track-2.2.0 → simple_track-2.2.1}/tests/test_frame.py +0 -0
- {simple_track-2.2.0 → simple_track-2.2.1}/tests/test_load.py +0 -0
- {simple_track-2.2.0 → simple_track-2.2.1}/tests/test_mwe_output.py +0 -0
- {simple_track-2.2.0 → simple_track-2.2.1}/tests/test_simple_track_and_load.py +0 -0
- {simple_track-2.2.0 → simple_track-2.2.1}/tests/test_utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: Simple-Track
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.1
|
|
4
4
|
Summary: Threshold-based object tracking algorithm for 2D data
|
|
5
5
|
Author-email: Adam Gainford <adam.gainford@reading.ac.uk>, Thorwald Stein <t.h.m.stein@reading.ac.uk>
|
|
6
6
|
License-Expression: MPL-2.0
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "Simple-Track"
|
|
7
|
-
version = "2.2.
|
|
7
|
+
version = "2.2.1"
|
|
8
8
|
authors = [
|
|
9
9
|
{ name="Adam Gainford", email="adam.gainford@reading.ac.uk" },
|
|
10
10
|
{ name="Thorwald Stein", email="t.h.m.stein@reading.ac.uk"}
|
|
@@ -43,4 +43,4 @@ testpaths = ["tests"]
|
|
|
43
43
|
|
|
44
44
|
[tool.ruff.lint]
|
|
45
45
|
select = ["E", "F", "B", "I", "UP", "SIM", "D101"]
|
|
46
|
-
ignore = ["SIM102"]
|
|
46
|
+
ignore = ["SIM102"]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: Simple-Track
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.1
|
|
4
4
|
Summary: Threshold-based object tracking algorithm for 2D data
|
|
5
5
|
Author-email: Adam Gainford <adam.gainford@reading.ac.uk>, Thorwald Stein <t.h.m.stein@reading.ac.uk>
|
|
6
6
|
License-Expression: MPL-2.0
|
|
@@ -311,11 +311,12 @@ class Feature:
|
|
|
311
311
|
|
|
312
312
|
# Reverse eigenvectors to be in (y,x) format, consistent with rest of package
|
|
313
313
|
# Native converts from numpy type to python type
|
|
314
|
+
# Real ensures types are not complex, which can happen with PCA decomposition
|
|
314
315
|
return (
|
|
315
|
-
native(major_unit_vector[::-1]),
|
|
316
|
-
native(minor_unit_vector[::-1]),
|
|
317
|
-
native(major_diameter / 2),
|
|
318
|
-
native(minor_diameter / 2),
|
|
316
|
+
native(np.real(major_unit_vector[::-1])),
|
|
317
|
+
native(np.real(minor_unit_vector[::-1])),
|
|
318
|
+
native(np.real(major_diameter / 2)),
|
|
319
|
+
native(np.real(minor_diameter / 2)),
|
|
319
320
|
)
|
|
320
321
|
|
|
321
322
|
def calculate_centroid(self) -> tuple:
|
|
@@ -768,13 +768,13 @@ class FrameTracker:
|
|
|
768
768
|
# Set the first value of the hist to 0 since this represents the background
|
|
769
769
|
overlap_hist[0] = 0
|
|
770
770
|
|
|
771
|
-
# Normalise overlap histogram by size of each feature in advected field only
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
)
|
|
771
|
+
# Normalise overlap histogram by size of each feature in advected field only.
|
|
772
|
+
# bincount computes all per-id pixel counts in a single pass; the previous
|
|
773
|
+
# per-id np.count_nonzero loop was O(max_id * domain) and dominated runtime
|
|
774
|
+
# for long sequences (feature_field holds persistent ids, which grow large).
|
|
775
|
+
norm_sizes = np.bincount(
|
|
776
|
+
advected_feature_field.ravel(), minlength=len(overlap_hist)
|
|
777
|
+
)[: len(overlap_hist)]
|
|
778
778
|
# Replace any zero sizes with 1 to avoid division by zero
|
|
779
779
|
norm_sizes = np.where(norm_sizes == 0, 1, norm_sizes)
|
|
780
780
|
overlap_normed = overlap_hist / norm_sizes
|
|
@@ -152,8 +152,15 @@ class Tracker:
|
|
|
152
152
|
|
|
153
153
|
# Now run flow solver between previous and current frame
|
|
154
154
|
prev_frame = self.timeline.get_previous_frame(frame.time)
|
|
155
|
-
# Set max id for assigning to new features
|
|
156
|
-
frame
|
|
155
|
+
# Set max id for assigning to new features.
|
|
156
|
+
# An all-quiet first frame leaves prev_frame.max_id None
|
|
157
|
+
# (identify_features returns early without setting it when no
|
|
158
|
+
# features are above threshold). Skip the carry-forward then;
|
|
159
|
+
# get_next_available_feature_id lazily initialises max_id from the
|
|
160
|
+
# frame's own feature_field, and there are no earlier ids to collide
|
|
161
|
+
# with.
|
|
162
|
+
if prev_frame.max_id is not None:
|
|
163
|
+
frame.max_id = prev_frame.max_id
|
|
157
164
|
# Get the flow field that translates features between the two frames
|
|
158
165
|
y_flow, x_flow = self.flow_solver.analyse_flow(prev_frame, frame)
|
|
159
166
|
|
|
@@ -573,7 +573,9 @@ def test_multiple_unequal_feature_unequal_flow_advection(
|
|
|
573
573
|
@pytest.mark.parametrize(
|
|
574
574
|
"test_dy_f0, test_dx_f0, test_dy_f1, test_dx_f1, f1_y_growth, expected_dy, expected_dx",
|
|
575
575
|
[
|
|
576
|
-
|
|
576
|
+
# First test shows inconsistent behaviour between different architectures (Linux vs MacOS), needs further refinement
|
|
577
|
+
# [10, 0, 0, 0, 7, 7, 0], # F0 advects, F1 grows by 7 -> expected dy = 7 (?)
|
|
578
|
+
# All other tests do not show the expected outcome on any architecture.
|
|
577
579
|
# [10, 0, 10, 0, 7, 17, 0], # F1 grows by 7 advects by 10, should get dy = 17, get 0
|
|
578
580
|
# [0, 0, 0, 5, 7, 7, 5], # F1 grows by 7 and dx=5, expect dy=7 and dx=5. get dy=0
|
|
579
581
|
# [0, 0, 5, 5, 7, 12, 5], # Expect dy=12, get 0
|
|
@@ -621,7 +623,8 @@ def test_growing_feature(
|
|
|
621
623
|
[10, 0, 15, 0, 10, 10, 0], # F1 advects 15 but shrinks 10. Expect dy=10 from f0
|
|
622
624
|
[0, 10, 0, 15, 5, 0, 10], # Similar behaviour if just dx rather than just dy
|
|
623
625
|
[10, 10, 15, 15, 5, 10, 10], # Also works if features move in diagonal
|
|
624
|
-
|
|
626
|
+
# Inconsistent behaviour between different architectures (Linux vs MacOS), needs further refinement
|
|
627
|
+
# [0, 0, 10, 10, 5, 0, 0], # If f0 is stationary but f1 moves, solver picks f0
|
|
625
628
|
[10, 10, 0, 0, 5, 10, 10], # If f0 moves and f1 is stationary, solver picks f0
|
|
626
629
|
],
|
|
627
630
|
)
|
|
@@ -446,7 +446,8 @@ def test_overlap_histogram_with_multiple_overlaps_and_different_labels(
|
|
|
446
446
|
],
|
|
447
447
|
[np.zeros((10), dtype=int), np.zeros((10), dtype=int), 1, 0, ArrayShapeError],
|
|
448
448
|
[np.zeros((5, 10), dtype=int), zero_arr, 1, 0, ArrayShapeError],
|
|
449
|
-
|
|
449
|
+
# This test should pass now that check_arrays converts to int type if values don't change
|
|
450
|
+
# [np.zeros((10, 10), dtype=float), np.zeros((10, 10)), 1, 0, ArrayTypeError],
|
|
450
451
|
[zero_arr, zero_arr, -1, 0, NegativeIDError],
|
|
451
452
|
[zero_arr, zero_arr, 1.5, 0, FloatIDError],
|
|
452
453
|
[zero_arr, zero_arr, 0, 0, ZeroIDError],
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|