valor-lite 0.35.0__py3-none-any.whl → 0.36.1__py3-none-any.whl

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.
@@ -19,7 +19,7 @@ def unpack_precision_recall_rocauc_into_metric_lists(
19
19
  score_thresholds: list[float],
20
20
  hardmax: bool,
21
21
  label_metadata: NDArray[np.int32],
22
- index_to_label: dict[int, str],
22
+ index_to_label: list[str],
23
23
  ) -> dict[MetricType, list[Metric]]:
24
24
  (
25
25
  counts,
@@ -38,7 +38,7 @@ def unpack_precision_recall_rocauc_into_metric_lists(
38
38
  value=float(rocauc[label_idx]),
39
39
  label=label,
40
40
  )
41
- for label_idx, label in index_to_label.items()
41
+ for label_idx, label in enumerate(index_to_label)
42
42
  if label_metadata[label_idx, 0] > 0
43
43
  ]
44
44
 
@@ -57,7 +57,7 @@ def unpack_precision_recall_rocauc_into_metric_lists(
57
57
  for score_idx, score_threshold in enumerate(score_thresholds)
58
58
  ]
59
59
 
60
- for label_idx, label in index_to_label.items():
60
+ for label_idx, label in enumerate(index_to_label):
61
61
  for score_idx, score_threshold in enumerate(score_thresholds):
62
62
 
63
63
  kwargs = {
@@ -105,8 +105,8 @@ def _unpack_confusion_matrix_value(
105
105
  confusion_matrix: NDArray[np.float64],
106
106
  number_of_labels: int,
107
107
  number_of_examples: int,
108
- index_to_uid: dict[int, str],
109
- index_to_label: dict[int, str],
108
+ index_to_datum_id: list[str],
109
+ index_to_label: list[str],
110
110
  ) -> dict[str, dict[str, dict[str, int | list[dict[str, str | float]]]]]:
111
111
  """
112
112
  Unpacks a numpy array of confusion matrix counts and examples.
@@ -137,7 +137,7 @@ def _unpack_confusion_matrix_value(
137
137
  ),
138
138
  "examples": [
139
139
  {
140
- "datum": index_to_uid[
140
+ "datum_id": index_to_datum_id[
141
141
  datum_idx(gt_label_idx, pd_label_idx, example_idx)
142
142
  ],
143
143
  "score": score_idx(
@@ -158,8 +158,8 @@ def _unpack_unmatched_ground_truths_value(
158
158
  unmatched_ground_truths: NDArray[np.int32],
159
159
  number_of_labels: int,
160
160
  number_of_examples: int,
161
- index_to_uid: dict[int, str],
162
- index_to_label: dict[int, str],
161
+ index_to_datum_id: list[str],
162
+ index_to_label: list[str],
163
163
  ) -> dict[str, dict[str, int | list[dict[str, str]]]]:
164
164
  """
165
165
  Unpacks a numpy array of unmatched ground truth counts and examples.
@@ -181,7 +181,11 @@ def _unpack_unmatched_ground_truths_value(
181
181
  0,
182
182
  ),
183
183
  "examples": [
184
- {"datum": index_to_uid[datum_idx(gt_label_idx, example_idx)]}
184
+ {
185
+ "datum_id": index_to_datum_id[
186
+ datum_idx(gt_label_idx, example_idx)
187
+ ]
188
+ }
185
189
  for example_idx in range(number_of_examples)
186
190
  if datum_idx(gt_label_idx, example_idx) >= 0
187
191
  ],
@@ -194,12 +198,12 @@ def unpack_confusion_matrix_into_metric_list(
194
198
  results: tuple[NDArray[np.float64], NDArray[np.int32]],
195
199
  score_thresholds: list[float],
196
200
  number_of_examples: int,
197
- index_to_uid: dict[int, str],
198
- index_to_label: dict[int, str],
201
+ index_to_datum_id: list[str],
202
+ index_to_label: list[str],
199
203
  ) -> list[Metric]:
200
204
 
201
205
  (confusion_matrix, unmatched_ground_truths) = results
202
- n_scores, n_labels, _, _ = confusion_matrix.shape
206
+ _, n_labels, _, _ = confusion_matrix.shape
203
207
  return [
204
208
  Metric.confusion_matrix(
205
209
  score_threshold=score_threshold,
@@ -209,7 +213,7 @@ def unpack_confusion_matrix_into_metric_list(
209
213
  number_of_labels=n_labels,
210
214
  number_of_examples=number_of_examples,
211
215
  index_to_label=index_to_label,
212
- index_to_uid=index_to_uid,
216
+ index_to_datum_id=index_to_datum_id,
213
217
  ),
214
218
  unmatched_ground_truths=_unpack_unmatched_ground_truths_value(
215
219
  unmatched_ground_truths=unmatched_ground_truths[
@@ -218,7 +222,7 @@ def unpack_confusion_matrix_into_metric_list(
218
222
  number_of_labels=n_labels,
219
223
  number_of_examples=number_of_examples,
220
224
  index_to_label=index_to_label,
221
- index_to_uid=index_to_uid,
225
+ index_to_datum_id=index_to_datum_id,
222
226
  ),
223
227
  )
224
228
  for score_idx, score_threshold in enumerate(score_thresholds)
@@ -0,0 +1,15 @@
1
+ class EmptyEvaluatorException(Exception):
2
+ def __init__(self):
3
+ super().__init__(
4
+ "evaluator cannot be finalized as it contains no data"
5
+ )
6
+
7
+
8
+ class EmptyFilterException(Exception):
9
+ def __init__(self, message: str):
10
+ super().__init__(message)
11
+
12
+
13
+ class InternalCacheException(Exception):
14
+ def __init__(self, message: str):
15
+ super().__init__(message)
@@ -1,5 +1,5 @@
1
1
  from .annotation import Bitmask, BoundingBox, Detection, Polygon
2
- from .manager import DataLoader, Evaluator
2
+ from .manager import DataLoader, Evaluator, Filter
3
3
  from .metric import Metric, MetricType
4
4
 
5
5
  __all__ = [
@@ -11,4 +11,5 @@ __all__ = [
11
11
  "MetricType",
12
12
  "DataLoader",
13
13
  "Evaluator",
14
+ "Filter",
14
15
  ]
@@ -1,4 +1,3 @@
1
- import warnings
2
1
  from enum import IntFlag, auto
3
2
 
4
3
  import numpy as np
@@ -221,6 +220,89 @@ def compute_label_metadata(
221
220
  return label_metadata
222
221
 
223
222
 
223
+ def filter_cache(
224
+ detailed_pairs: NDArray[np.float64],
225
+ mask_datums: NDArray[np.bool_],
226
+ mask_predictions: NDArray[np.bool_],
227
+ mask_ground_truths: NDArray[np.bool_],
228
+ n_labels: int,
229
+ ) -> tuple[NDArray[np.float64], NDArray[np.float64], NDArray[np.int32],]:
230
+ """
231
+ Performs filtering on a detailed cache.
232
+
233
+ Parameters
234
+ ----------
235
+ detailed_pairs : NDArray[float64]
236
+ A list of sorted detailed pairs with size (N, 7).
237
+ mask_datums : NDArray[bool]
238
+ A boolean mask with size (N,).
239
+ mask_ground_truths : NDArray[bool]
240
+ A boolean mask with size (N,).
241
+ mask_predictions : NDArray[bool]
242
+ A boolean mask with size (N,).
243
+ n_labels : int
244
+ The total number of unique labels.
245
+
246
+ Returns
247
+ -------
248
+ NDArray[float64]
249
+ Filtered detailed pairs.
250
+ NDArray[float64]
251
+ Filtered ranked pairs.
252
+ NDArray[int32]
253
+ Label metadata.
254
+ """
255
+ # filter datums
256
+ detailed_pairs = detailed_pairs[mask_datums].copy()
257
+
258
+ # filter ground truths
259
+ if mask_ground_truths.any():
260
+ invalid_groundtruth_indices = np.where(mask_ground_truths)[0]
261
+ detailed_pairs[
262
+ invalid_groundtruth_indices[:, None], (1, 3, 5)
263
+ ] = np.array([[-1, -1, 0]])
264
+
265
+ # filter predictions
266
+ if mask_predictions.any():
267
+ invalid_prediction_indices = np.where(mask_predictions)[0]
268
+ detailed_pairs[
269
+ invalid_prediction_indices[:, None], (2, 4, 5, 6)
270
+ ] = np.array([[-1, -1, 0, -1]])
271
+
272
+ # filter null pairs
273
+ mask_null_pairs = np.all(
274
+ np.isclose(
275
+ detailed_pairs[:, 1:5],
276
+ np.array([-1.0, -1.0, -1.0, -1.0]),
277
+ ),
278
+ axis=1,
279
+ )
280
+ detailed_pairs = detailed_pairs[~mask_null_pairs]
281
+
282
+ # sorts by score, iou with ground truth id as a tie-breaker
283
+ indices = np.lexsort(
284
+ (
285
+ detailed_pairs[:, 1], # ground truth id
286
+ -detailed_pairs[:, 5], # iou
287
+ -detailed_pairs[:, 6], # score
288
+ )
289
+ )
290
+ detailed_pairs = detailed_pairs[indices]
291
+ label_metadata = compute_label_metadata(
292
+ ids=detailed_pairs[:, :5].astype(np.int32),
293
+ n_labels=n_labels,
294
+ )
295
+ ranked_pairs = rank_pairs(
296
+ detailed_pairs=detailed_pairs,
297
+ label_metadata=label_metadata,
298
+ )
299
+ return (
300
+ detailed_pairs,
301
+ ranked_pairs,
302
+ label_metadata,
303
+ )
304
+
305
+
224
306
  def rank_pairs(
225
307
  detailed_pairs: NDArray[np.float64],
226
308
  label_metadata: NDArray[np.int32],
@@ -350,15 +432,6 @@ def compute_precion_recall(
350
432
  counts = np.zeros((n_ious, n_scores, n_labels, 6), dtype=np.float64)
351
433
  pr_curve = np.zeros((n_ious, n_labels, 101, 2))
352
434
 
353
- if ranked_pairs.size == 0:
354
- warnings.warn("no valid ranked pairs")
355
- return (
356
- (average_precision, mAP),
357
- (average_recall, mAR),
358
- counts,
359
- pr_curve,
360
- )
361
-
362
435
  # start computation
363
436
  ids = ranked_pairs[:, :5].astype(np.int32)
364
437
  gt_ids = ids[:, 1]