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.
Files changed (31) hide show
  1. {simple_track-2.2.0 → simple_track-2.2.1}/PKG-INFO +1 -1
  2. {simple_track-2.2.0 → simple_track-2.2.1}/pyproject.toml +2 -2
  3. {simple_track-2.2.0 → simple_track-2.2.1}/src/Simple_Track.egg-info/PKG-INFO +1 -1
  4. {simple_track-2.2.0 → simple_track-2.2.1}/src/simpletrack/feature.py +5 -4
  5. {simple_track-2.2.0 → simple_track-2.2.1}/src/simpletrack/frame_tracker.py +7 -7
  6. {simple_track-2.2.0 → simple_track-2.2.1}/src/simpletrack/track.py +9 -2
  7. {simple_track-2.2.0 → simple_track-2.2.1}/tests/test_flow_solver.py +5 -2
  8. {simple_track-2.2.0 → simple_track-2.2.1}/tests/test_frame_tracker.py +2 -1
  9. {simple_track-2.2.0 → simple_track-2.2.1}/LICENSE +0 -0
  10. {simple_track-2.2.0 → simple_track-2.2.1}/README.md +0 -0
  11. {simple_track-2.2.0 → simple_track-2.2.1}/setup.cfg +0 -0
  12. {simple_track-2.2.0 → simple_track-2.2.1}/src/Simple_Track.egg-info/SOURCES.txt +0 -0
  13. {simple_track-2.2.0 → simple_track-2.2.1}/src/Simple_Track.egg-info/dependency_links.txt +0 -0
  14. {simple_track-2.2.0 → simple_track-2.2.1}/src/Simple_Track.egg-info/entry_points.txt +0 -0
  15. {simple_track-2.2.0 → simple_track-2.2.1}/src/Simple_Track.egg-info/requires.txt +0 -0
  16. {simple_track-2.2.0 → simple_track-2.2.1}/src/Simple_Track.egg-info/top_level.txt +0 -0
  17. {simple_track-2.2.0 → simple_track-2.2.1}/src/run_simple_track.py +0 -0
  18. {simple_track-2.2.0 → simple_track-2.2.1}/src/simpletrack/__init__.py +0 -0
  19. {simple_track-2.2.0 → simple_track-2.2.1}/src/simpletrack/exceptions.py +0 -0
  20. {simple_track-2.2.0 → simple_track-2.2.1}/src/simpletrack/flow_solver.py +0 -0
  21. {simple_track-2.2.0 → simple_track-2.2.1}/src/simpletrack/frame.py +0 -0
  22. {simple_track-2.2.0 → simple_track-2.2.1}/src/simpletrack/frame_output.py +0 -0
  23. {simple_track-2.2.0 → simple_track-2.2.1}/src/simpletrack/load.py +0 -0
  24. {simple_track-2.2.0 → simple_track-2.2.1}/src/simpletrack/utils.py +0 -0
  25. {simple_track-2.2.0 → simple_track-2.2.1}/tests/test_cli.py +0 -0
  26. {simple_track-2.2.0 → simple_track-2.2.1}/tests/test_feature.py +0 -0
  27. {simple_track-2.2.0 → simple_track-2.2.1}/tests/test_frame.py +0 -0
  28. {simple_track-2.2.0 → simple_track-2.2.1}/tests/test_load.py +0 -0
  29. {simple_track-2.2.0 → simple_track-2.2.1}/tests/test_mwe_output.py +0 -0
  30. {simple_track-2.2.0 → simple_track-2.2.1}/tests/test_simple_track_and_load.py +0 -0
  31. {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.0
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.0"
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.0
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
- norm_sizes = np.array(
773
- [
774
- np.count_nonzero(advected_feature_field == idx)
775
- for idx in range(len(overlap_hist))
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.max_id = prev_frame.max_id
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
- [10, 0, 0, 0, 7, 7, 0], # F0 advects, F1 grows by 7 -> expected dy = 7 (?)
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
- [0, 0, 10, 10, 5, 0, 0], # If f0 is stationary but f1 moves, solver picks f0
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
- [np.zeros((10, 10), dtype=float), np.zeros((10, 10)), 1, 0, ArrayTypeError],
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