Simple-Track 2.0.4__tar.gz → 2.0.5__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.0.4 → simple_track-2.0.5}/PKG-INFO +9 -7
- {simple_track-2.0.4 → simple_track-2.0.5}/README.md +8 -6
- {simple_track-2.0.4 → simple_track-2.0.5}/pyproject.toml +1 -1
- {simple_track-2.0.4 → simple_track-2.0.5}/src/Simple_Track.egg-info/PKG-INFO +9 -7
- {simple_track-2.0.4 → simple_track-2.0.5}/src/simpletrack/feature.py +21 -8
- {simple_track-2.0.4 → simple_track-2.0.5}/src/simpletrack/frame.py +5 -1
- {simple_track-2.0.4 → simple_track-2.0.5}/src/simpletrack/track.py +1 -1
- {simple_track-2.0.4 → simple_track-2.0.5}/tests/test_frame.py +28 -3
- {simple_track-2.0.4 → simple_track-2.0.5}/LICENSE +0 -0
- {simple_track-2.0.4 → simple_track-2.0.5}/setup.cfg +0 -0
- {simple_track-2.0.4 → simple_track-2.0.5}/src/Simple_Track.egg-info/SOURCES.txt +0 -0
- {simple_track-2.0.4 → simple_track-2.0.5}/src/Simple_Track.egg-info/dependency_links.txt +0 -0
- {simple_track-2.0.4 → simple_track-2.0.5}/src/Simple_Track.egg-info/entry_points.txt +0 -0
- {simple_track-2.0.4 → simple_track-2.0.5}/src/Simple_Track.egg-info/requires.txt +0 -0
- {simple_track-2.0.4 → simple_track-2.0.5}/src/Simple_Track.egg-info/top_level.txt +0 -0
- {simple_track-2.0.4 → simple_track-2.0.5}/src/run_simple_track.py +0 -0
- {simple_track-2.0.4 → simple_track-2.0.5}/src/simpletrack/__init__.py +0 -0
- {simple_track-2.0.4 → simple_track-2.0.5}/src/simpletrack/exceptions.py +0 -0
- {simple_track-2.0.4 → simple_track-2.0.5}/src/simpletrack/flow_solver.py +0 -0
- {simple_track-2.0.4 → simple_track-2.0.5}/src/simpletrack/frame_output.py +0 -0
- {simple_track-2.0.4 → simple_track-2.0.5}/src/simpletrack/frame_tracker.py +0 -0
- {simple_track-2.0.4 → simple_track-2.0.5}/src/simpletrack/load.py +0 -0
- {simple_track-2.0.4 → simple_track-2.0.5}/src/simpletrack/utils.py +0 -0
- {simple_track-2.0.4 → simple_track-2.0.5}/tests/test_feature.py +0 -0
- {simple_track-2.0.4 → simple_track-2.0.5}/tests/test_flow_solver.py +0 -0
- {simple_track-2.0.4 → simple_track-2.0.5}/tests/test_frame_tracker.py +0 -0
- {simple_track-2.0.4 → simple_track-2.0.5}/tests/test_mwe_output.py +0 -0
- {simple_track-2.0.4 → simple_track-2.0.5}/tests/test_simple_track_and_load.py +0 -0
- {simple_track-2.0.4 → simple_track-2.0.5}/tests/test_utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: Simple-Track
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.5
|
|
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
|
|
@@ -33,13 +33,15 @@ Features are tracked between consecutive frames of data by projecting feature fi
|
|
|
33
33
|
|
|
34
34
|
# Installation
|
|
35
35
|
|
|
36
|
-
Simple-Track can be installed using PyPi:
|
|
36
|
+
Simple-Track can be installed using PyPi or conda-forge:
|
|
37
37
|
|
|
38
38
|
```
|
|
39
39
|
python3 -m pip install simple-track
|
|
40
40
|
```
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
```
|
|
42
|
+
conda install conda-forge::simple-track
|
|
43
|
+
```
|
|
44
|
+
Coming soon to uv
|
|
43
45
|
|
|
44
46
|
# User Guide
|
|
45
47
|
|
|
@@ -177,10 +179,10 @@ Fields (`.field` files):
|
|
|
177
179
|
|
|
178
180
|
Features (`.csv` or `.txt` files):
|
|
179
181
|
* ID: Unique feature identifier that persists between frames (i.e., a feature retains the same id across all frames that it is tracked).
|
|
180
|
-
*
|
|
181
|
-
*
|
|
182
|
+
* centroid: (y, x) tuple containing central location of feature.
|
|
183
|
+
* size: Number of pixels spanned by the feature.
|
|
182
184
|
* dydx: (dy, dx) tuple containing motion vector that translated feature to its location in the current frame from the previous frame.
|
|
183
|
-
*
|
|
185
|
+
* max: Maximum value contained within the feature in the input data.
|
|
184
186
|
* lifetime: Number of timesteps the feature has existed for.
|
|
185
187
|
* accreted: List of IDs of features that were accreted by this feature, if applicable.
|
|
186
188
|
* parent: ID of parent feature that this feature split from, if applicable
|
|
@@ -11,13 +11,15 @@ Features are tracked between consecutive frames of data by projecting feature fi
|
|
|
11
11
|
|
|
12
12
|
# Installation
|
|
13
13
|
|
|
14
|
-
Simple-Track can be installed using PyPi:
|
|
14
|
+
Simple-Track can be installed using PyPi or conda-forge:
|
|
15
15
|
|
|
16
16
|
```
|
|
17
17
|
python3 -m pip install simple-track
|
|
18
18
|
```
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
```
|
|
20
|
+
conda install conda-forge::simple-track
|
|
21
|
+
```
|
|
22
|
+
Coming soon to uv
|
|
21
23
|
|
|
22
24
|
# User Guide
|
|
23
25
|
|
|
@@ -155,10 +157,10 @@ Fields (`.field` files):
|
|
|
155
157
|
|
|
156
158
|
Features (`.csv` or `.txt` files):
|
|
157
159
|
* ID: Unique feature identifier that persists between frames (i.e., a feature retains the same id across all frames that it is tracked).
|
|
158
|
-
*
|
|
159
|
-
*
|
|
160
|
+
* centroid: (y, x) tuple containing central location of feature.
|
|
161
|
+
* size: Number of pixels spanned by the feature.
|
|
160
162
|
* dydx: (dy, dx) tuple containing motion vector that translated feature to its location in the current frame from the previous frame.
|
|
161
|
-
*
|
|
163
|
+
* max: Maximum value contained within the feature in the input data.
|
|
162
164
|
* lifetime: Number of timesteps the feature has existed for.
|
|
163
165
|
* accreted: List of IDs of features that were accreted by this feature, if applicable.
|
|
164
166
|
* parent: ID of parent feature that this feature split from, if applicable
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: Simple-Track
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.5
|
|
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
|
|
@@ -33,13 +33,15 @@ Features are tracked between consecutive frames of data by projecting feature fi
|
|
|
33
33
|
|
|
34
34
|
# Installation
|
|
35
35
|
|
|
36
|
-
Simple-Track can be installed using PyPi:
|
|
36
|
+
Simple-Track can be installed using PyPi or conda-forge:
|
|
37
37
|
|
|
38
38
|
```
|
|
39
39
|
python3 -m pip install simple-track
|
|
40
40
|
```
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
```
|
|
42
|
+
conda install conda-forge::simple-track
|
|
43
|
+
```
|
|
44
|
+
Coming soon to uv
|
|
43
45
|
|
|
44
46
|
# User Guide
|
|
45
47
|
|
|
@@ -177,10 +179,10 @@ Fields (`.field` files):
|
|
|
177
179
|
|
|
178
180
|
Features (`.csv` or `.txt` files):
|
|
179
181
|
* ID: Unique feature identifier that persists between frames (i.e., a feature retains the same id across all frames that it is tracked).
|
|
180
|
-
*
|
|
181
|
-
*
|
|
182
|
+
* centroid: (y, x) tuple containing central location of feature.
|
|
183
|
+
* size: Number of pixels spanned by the feature.
|
|
182
184
|
* dydx: (dy, dx) tuple containing motion vector that translated feature to its location in the current frame from the previous frame.
|
|
183
|
-
*
|
|
185
|
+
* max: Maximum value contained within the feature in the input data.
|
|
184
186
|
* lifetime: Number of timesteps the feature has existed for.
|
|
185
187
|
* accreted: List of IDs of features that were accreted by this feature, if applicable.
|
|
186
188
|
* parent: ID of parent feature that this feature split from, if applicable
|
|
@@ -9,7 +9,7 @@ from simpletrack.utils import check_arrays, check_valid_ids, native
|
|
|
9
9
|
class Feature:
|
|
10
10
|
"""
|
|
11
11
|
Object containing details about a specific feature, including its id, time,
|
|
12
|
-
centroid,
|
|
12
|
+
centroid, maximum value, lifetime, and whether it has undergone any
|
|
13
13
|
mergers of splits in the current timestep.
|
|
14
14
|
"""
|
|
15
15
|
|
|
@@ -30,7 +30,8 @@ class Feature:
|
|
|
30
30
|
self._parent = None
|
|
31
31
|
self._children = []
|
|
32
32
|
self._dydx = ()
|
|
33
|
-
self.
|
|
33
|
+
self._max = None
|
|
34
|
+
self._mean = None
|
|
34
35
|
|
|
35
36
|
def __repr__(self) -> str:
|
|
36
37
|
repr_str = f"Feature id: {self._id} (provisionally {self._provisional_id}), "
|
|
@@ -140,11 +141,18 @@ class Feature:
|
|
|
140
141
|
return native(self._dydx)
|
|
141
142
|
|
|
142
143
|
@property
|
|
143
|
-
def
|
|
144
|
+
def max(self) -> float:
|
|
144
145
|
"""
|
|
145
146
|
Maximum value of the Feature in the raw input data
|
|
146
147
|
"""
|
|
147
|
-
return self.
|
|
148
|
+
return self._max
|
|
149
|
+
|
|
150
|
+
@property
|
|
151
|
+
def mean(self) -> float:
|
|
152
|
+
"""
|
|
153
|
+
Mean value of the Feature in the raw input data
|
|
154
|
+
"""
|
|
155
|
+
return self._mean
|
|
148
156
|
|
|
149
157
|
@coords.setter
|
|
150
158
|
def coords(self, new_coords: NDArray[np.integer]) -> None:
|
|
@@ -184,9 +192,13 @@ class Feature:
|
|
|
184
192
|
id_of_accreting_feature = check_valid_ids(id_of_accreting_feature)
|
|
185
193
|
self._accreted_in_next_frame_by = id_of_accreting_feature
|
|
186
194
|
|
|
187
|
-
@
|
|
188
|
-
def
|
|
189
|
-
self.
|
|
195
|
+
@max.setter
|
|
196
|
+
def max(self, max_val: float) -> None:
|
|
197
|
+
self._max = max_val
|
|
198
|
+
|
|
199
|
+
@mean.setter
|
|
200
|
+
def mean(self, mean_val: float) -> None:
|
|
201
|
+
self._mean = mean_val
|
|
190
202
|
|
|
191
203
|
def calculate_centroid(self) -> tuple:
|
|
192
204
|
"""
|
|
@@ -279,7 +291,8 @@ class Feature:
|
|
|
279
291
|
"size": self.get_size(),
|
|
280
292
|
# native() does not convert dydx to python type for some reason
|
|
281
293
|
"dydx": tuple([val.item() for val in self._dydx]),
|
|
282
|
-
"
|
|
294
|
+
"max": self._max,
|
|
295
|
+
"mean": self._mean,
|
|
283
296
|
"lifetime": self._lifetime,
|
|
284
297
|
"accreted": self._accreted,
|
|
285
298
|
# This will not be output properly in the current workflow, since each
|
|
@@ -211,7 +211,8 @@ class Frame:
|
|
|
211
211
|
)
|
|
212
212
|
# If raw field is not None, use this to find max value within Feature
|
|
213
213
|
if self.raw_field is not None:
|
|
214
|
-
feature.
|
|
214
|
+
feature.max = np.max(self.raw_field[feature_mask])
|
|
215
|
+
feature.mean = np.mean(self.raw_field[feature_mask])
|
|
215
216
|
self._features[feature_id] = feature
|
|
216
217
|
|
|
217
218
|
def assign_displacements(self, y_flow: NDArray, x_flow: NDArray) -> None:
|
|
@@ -387,6 +388,9 @@ class Timeline:
|
|
|
387
388
|
def __init__(self):
|
|
388
389
|
self.timeline = {}
|
|
389
390
|
|
|
391
|
+
def __len__(self) -> int:
|
|
392
|
+
return len(self.timeline)
|
|
393
|
+
|
|
390
394
|
def add_to_timelime(self, frame: Frame) -> None:
|
|
391
395
|
"""
|
|
392
396
|
Add the input frame to the timeline, using the frame.get_time() to
|
|
@@ -58,7 +58,7 @@ class Tracker:
|
|
|
58
58
|
self.frame_tracker = FrameTracker()
|
|
59
59
|
|
|
60
60
|
if "OUTPUT" in self.config:
|
|
61
|
-
self.skip_tracking = self.config["
|
|
61
|
+
self.skip_tracking = self.config["OUTPUT"].get("skip_tracking", False)
|
|
62
62
|
output_path = self.config["OUTPUT"].get("path", "./output")
|
|
63
63
|
expt_name = self.config["OUTPUT"].get(
|
|
64
64
|
"experiment_name", "Simple-Track Experiment"
|
|
@@ -103,7 +103,7 @@ def test_populate_features_valid_feature_field():
|
|
|
103
103
|
assert test_frame.features == expected_dict
|
|
104
104
|
|
|
105
105
|
|
|
106
|
-
def
|
|
106
|
+
def test_populate_features_sets_max_property():
|
|
107
107
|
test_time = dt.datetime.now()
|
|
108
108
|
test_frame = Frame()
|
|
109
109
|
test_frame.time = test_time
|
|
@@ -123,8 +123,33 @@ def test_populate_features_sets_extreme_property():
|
|
|
123
123
|
test_frame.raw_field = test_raw_field
|
|
124
124
|
test_frame.populate_features()
|
|
125
125
|
|
|
126
|
-
assert test_frame.get_feature(1).
|
|
127
|
-
assert test_frame.get_feature(2).
|
|
126
|
+
assert test_frame.get_feature(1).max == 10
|
|
127
|
+
assert test_frame.get_feature(2).max == 20
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def test_populate_features_sets_mean_property():
|
|
131
|
+
test_time = dt.datetime.now()
|
|
132
|
+
test_frame = Frame()
|
|
133
|
+
test_frame.time = test_time
|
|
134
|
+
|
|
135
|
+
test_feature_field = test_field.copy()
|
|
136
|
+
test_feature_field[2:6, 2:6] = 1
|
|
137
|
+
test_feature_field[6:9, 6:9] = 2
|
|
138
|
+
|
|
139
|
+
test_raw_field = test_field.copy()
|
|
140
|
+
test_raw_field[2:6, 2:6] = 10
|
|
141
|
+
test_raw_field[2:6, 4:6] = 50
|
|
142
|
+
test_raw_field[6:9, 6:9] = 20
|
|
143
|
+
# Set another higher maximum within the field to check mean
|
|
144
|
+
# only picks up the values within the feature mask
|
|
145
|
+
test_raw_field[0:2, 0:2] = 100
|
|
146
|
+
|
|
147
|
+
test_frame.feature_field = test_feature_field
|
|
148
|
+
test_frame.raw_field = test_raw_field
|
|
149
|
+
test_frame.populate_features()
|
|
150
|
+
|
|
151
|
+
assert test_frame.get_feature(1).mean == 30
|
|
152
|
+
assert test_frame.get_feature(2).mean == 20
|
|
128
153
|
|
|
129
154
|
|
|
130
155
|
def test_populate_features_invalid_negative_features():
|
|
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
|