dataeval 1.1.3__tar.gz → 1.1.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.
Files changed (182) hide show
  1. {dataeval-1.1.3 → dataeval-1.1.5}/PKG-INFO +1 -1
  2. {dataeval-1.1.3 → dataeval-1.1.5}/pyproject.toml +1 -4
  3. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/_version.py +2 -2
  4. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/extractors/_bovw.py +4 -2
  5. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/quality/_outliers.py +5 -4
  6. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/utils/_internal.py +8 -2
  7. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/utils/preprocessing.py +1 -1
  8. {dataeval-1.1.3 → dataeval-1.1.5}/.gitignore +0 -0
  9. {dataeval-1.1.3 → dataeval-1.1.5}/LICENSE +0 -0
  10. {dataeval-1.1.3 → dataeval-1.1.5}/README.md +0 -0
  11. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/__init__.py +0 -0
  12. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/_embeddings.py +0 -0
  13. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/_experimental.py +0 -0
  14. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/_helpers.py +0 -0
  15. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/_log.py +0 -0
  16. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/_metadata/__init__.py +0 -0
  17. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/_metadata/_aggregate.py +0 -0
  18. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/_metadata/_columns.py +0 -0
  19. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/_metadata/_deprecated.py +0 -0
  20. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/_metadata/_encoding.py +0 -0
  21. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/_metadata/_entry_legacy.py +0 -0
  22. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/_metadata/_filters.py +0 -0
  23. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/_metadata/_input.py +0 -0
  24. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/_metadata/_keyed.py +0 -0
  25. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/_metadata/_links.py +0 -0
  26. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/_metadata/_loading.py +0 -0
  27. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/_metadata/_metadata.py +0 -0
  28. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/_metadata/_serialize.py +0 -0
  29. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/_metadata/_store.py +0 -0
  30. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/_metadata/_structurers/__init__.py +0 -0
  31. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/_metadata/_structurers/_accumulator.py +0 -0
  32. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/_metadata/_structurers/_base.py +0 -0
  33. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/_metadata/_structurers/_block.py +0 -0
  34. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/_metadata/_structurers/_classification.py +0 -0
  35. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/_metadata/_structurers/_data.py +0 -0
  36. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/_metadata/_structurers/_dataset.py +0 -0
  37. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/_metadata/_structurers/_detection.py +0 -0
  38. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/_metadata/_structurers/_factors.py +0 -0
  39. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/_metadata/_structurers/_frames.py +0 -0
  40. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/_metadata/_structurers/_gather.py +0 -0
  41. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/_metadata/_structurers/_instances.py +0 -0
  42. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/_metadata/_structurers/_layout.py +0 -0
  43. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/_metadata/_structurers/_ordering.py +0 -0
  44. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/_metadata/_structurers/_propagation.py +0 -0
  45. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/_metadata/_structurers/_reporting.py +0 -0
  46. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/_metadata/_structurers/_reserved.py +0 -0
  47. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/_metadata/_structurers/_select.py +0 -0
  48. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/_metadata/_structurers/_source_index.py +0 -0
  49. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/_metadata/_structurers/_tracking.py +0 -0
  50. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/_ontology.py +0 -0
  51. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/bias/__init__.py +0 -0
  52. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/bias/_balance.py +0 -0
  53. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/bias/_diversity.py +0 -0
  54. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/bias/_parity.py +0 -0
  55. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/config.py +0 -0
  56. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/core/__init__.py +0 -0
  57. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/core/_ber.py +0 -0
  58. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/core/_bin.py +0 -0
  59. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/core/_calculators/__init__.py +0 -0
  60. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/core/_calculators/_base.py +0 -0
  61. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/core/_calculators/_cache.py +0 -0
  62. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/core/_calculators/_dimensionstats.py +0 -0
  63. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/core/_calculators/_hashstats.py +0 -0
  64. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/core/_calculators/_pixelstats.py +0 -0
  65. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/core/_calculators/_register.py +0 -0
  66. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/core/_calculators/_registry.py +0 -0
  67. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/core/_calculators/_visualstats.py +0 -0
  68. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/core/_clusterer.py +0 -0
  69. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/core/_completeness.py +0 -0
  70. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/core/_compute_ratios.py +0 -0
  71. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/core/_compute_stats.py +0 -0
  72. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/core/_coverage.py +0 -0
  73. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/core/_divergence.py +0 -0
  74. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/core/_diversity.py +0 -0
  75. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/core/_fast_hdbscan/_cluster_trees.py +0 -0
  76. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/core/_fast_hdbscan/_disjoint_set.py +0 -0
  77. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/core/_fast_hdbscan/_mst.py +0 -0
  78. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/core/_feature_distance.py +0 -0
  79. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/core/_hash.py +0 -0
  80. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/core/_label_alignment.py +0 -0
  81. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/core/_label_coverage.py +0 -0
  82. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/core/_label_errors.py +0 -0
  83. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/core/_label_parity.py +0 -0
  84. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/core/_label_reconciliation.py +0 -0
  85. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/core/_label_stats.py +0 -0
  86. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/core/_metadata_insights.py +0 -0
  87. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/core/_mst.py +0 -0
  88. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/core/_mutual_info.py +0 -0
  89. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/core/_nullmodel.py +0 -0
  90. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/core/_ontology_validation.py +0 -0
  91. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/core/_parity.py +0 -0
  92. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/core/_rank.py +0 -0
  93. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/core/_track_stats.py +0 -0
  94. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/core/_uap.py +0 -0
  95. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/data/__init__.py +0 -0
  96. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/data/_classbalance.py +0 -0
  97. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/data/_classfilter.py +0 -0
  98. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/data/_crop.py +0 -0
  99. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/data/_crops.py +0 -0
  100. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/data/_geometry.py +0 -0
  101. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/data/_indices.py +0 -0
  102. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/data/_invalidates.py +0 -0
  103. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/data/_limit.py +0 -0
  104. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/data/_merge.py +0 -0
  105. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/data/_relabel.py +0 -0
  106. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/data/_resize.py +0 -0
  107. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/data/_reverse.py +0 -0
  108. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/data/_selectchannels.py +0 -0
  109. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/data/_shuffle.py +0 -0
  110. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/data/_split.py +0 -0
  111. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/data/_torchvision.py +0 -0
  112. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/data/_tracks.py +0 -0
  113. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/data/_unzip.py +0 -0
  114. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/data/_view.py +0 -0
  115. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/exceptions.py +0 -0
  116. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/extractors/__init__.py +0 -0
  117. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/extractors/_flatten.py +0 -0
  118. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/extractors/_geometry.py +0 -0
  119. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/extractors/_onnx.py +0 -0
  120. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/extractors/_scores.py +0 -0
  121. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/extractors/_torch.py +0 -0
  122. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/extractors/_uncertainty.py +0 -0
  123. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/flags.py +0 -0
  124. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/models/__init__.py +0 -0
  125. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/models/_backends.py +0 -0
  126. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/models/_input.py +0 -0
  127. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/models/_metadata.py +0 -0
  128. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/models/_predictors.py +0 -0
  129. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/performance/__init__.py +0 -0
  130. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/performance/_aggregator.py +0 -0
  131. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/performance/_output.py +0 -0
  132. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/performance/_sufficiency.py +0 -0
  133. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/performance/schedules.py +0 -0
  134. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/protocols.py +0 -0
  135. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/py.typed +0 -0
  136. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/quality/__init__.py +0 -0
  137. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/quality/_duplicates.py +0 -0
  138. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/quality/_shared.py +0 -0
  139. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/scope/__init__.py +0 -0
  140. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/scope/_coverage.py +0 -0
  141. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/scope/_prioritize.py +0 -0
  142. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/scope/_representation.py +0 -0
  143. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/selection/__init__.py +0 -0
  144. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/shift/__init__.py +0 -0
  145. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/shift/_drift/__init__.py +0 -0
  146. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/shift/_drift/_base.py +0 -0
  147. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/shift/_drift/_chunk.py +0 -0
  148. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/shift/_drift/_domain_classifier.py +0 -0
  149. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/shift/_drift/_kneighbors.py +0 -0
  150. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/shift/_drift/_mmd.py +0 -0
  151. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/shift/_drift/_reconstruction.py +0 -0
  152. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/shift/_drift/_univariate.py +0 -0
  153. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/shift/_drift/_wasserstein.py +0 -0
  154. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/shift/_ood/__init__.py +0 -0
  155. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/shift/_ood/_base.py +0 -0
  156. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/shift/_ood/_domain_classifier.py +0 -0
  157. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/shift/_ood/_kneighbors.py +0 -0
  158. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/shift/_ood/_reconstruction.py +0 -0
  159. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/shift/_shared/__init__.py +0 -0
  160. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/shift/_shared/_domain_classifier.py +0 -0
  161. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/shift/_shared/_kneighbors.py +0 -0
  162. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/shift/_shared/_reconstruction.py +0 -0
  163. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/shift/update_strategies.py +0 -0
  164. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/types/__init__.py +0 -0
  165. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/types/_array.py +0 -0
  166. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/types/_config.py +0 -0
  167. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/types/_evaluator.py +0 -0
  168. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/types/_execution.py +0 -0
  169. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/types/_factors.py +0 -0
  170. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/types/_index.py +0 -0
  171. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/types/_ontology.py +0 -0
  172. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/types/_output.py +0 -0
  173. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/types/_schema.py +0 -0
  174. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/types/_track.py +0 -0
  175. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/utils/__init__.py +0 -0
  176. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/utils/_validate.py +0 -0
  177. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/utils/data.py +0 -0
  178. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/utils/losses.py +0 -0
  179. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/utils/models.py +0 -0
  180. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/utils/onnx.py +0 -0
  181. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/utils/thresholds.py +0 -0
  182. {dataeval-1.1.3 → dataeval-1.1.5}/src/dataeval/utils/training.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: dataeval
3
- Version: 1.1.3
3
+ Version: 1.1.5
4
4
  Summary: DataEval provides a simple interface to characterize image data and its impact on model performance across classification and object-detection tasks
5
5
  Project-URL: Homepage, https://dataeval.ai/
6
6
  Project-URL: Repository, https://github.com/aria-ml/dataeval/
@@ -107,10 +107,6 @@ lint = [
107
107
  docsync = [
108
108
  "jupytext>=1.19.1",
109
109
  ]
110
- docker = [
111
- "jinja2>=3.1",
112
- "pyyaml>=6.0",
113
- ]
114
110
  test = [
115
111
  "coverage[toml]>=7.6",
116
112
  "filelock>=3.20.3",
@@ -318,6 +314,7 @@ markers = [
318
314
  "required: marks tests for required features",
319
315
  "optional: marks tests for optional features",
320
316
  "cuda: marks tests that require cuda",
317
+ "performance: marks verification tests that time workloads or measure memory",
321
318
  ]
322
319
 
323
320
  [tool.coverage.run]
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
18
18
  commit_id: str | None
19
19
  __commit_id__: str | None
20
20
 
21
- __version__ = version = '1.1.3'
22
- __version_tuple__ = version_tuple = (1, 1, 3)
21
+ __version__ = version = '1.1.5'
22
+ __version_tuple__ = version_tuple = (1, 1, 5)
23
23
 
24
24
  __commit_id__ = commit_id = None
@@ -208,7 +208,9 @@ class BoVWExtractor:
208
208
  If no SIFT features are found in any image. This typically occurs
209
209
  when all images are uniform (e.g., solid color).
210
210
  """
211
- with PoolWrapper(get_max_processes(), context="spawn") as pool:
211
+ # Threads, not processes: OpenCV and k-means release the GIL, so threads scale SIFT
212
+ # without paying process startup and model pickling on every Embeddings batch.
213
+ with PoolWrapper(get_max_processes(), context="threads") as pool:
212
214
  all_descriptors = [
213
215
  des for _, des in sorted(pool.imap_unordered(_extract_single, enumerate(data))) if len(des) > 0
214
216
  ]
@@ -269,7 +271,7 @@ class BoVWExtractor:
269
271
 
270
272
  result = np.zeros((len(images), n_clusters), dtype=np.float32)
271
273
 
272
- with PoolWrapper(get_max_processes(), context="spawn") as pool:
274
+ with PoolWrapper(get_max_processes(), context="threads") as pool:
273
275
  for idx, histogram in pool.imap_unordered(
274
276
  partial(_transform_single, kmeans=self._kmeans, n_clusters=n_clusters),
275
277
  enumerate(images),
@@ -84,8 +84,8 @@ class OutliersOutput(DataFrameOutput, Generic[TOutliers]):
84
84
  Preserved across re-detection calls unless overridden via
85
85
  :meth:`with_threshold`.
86
86
  dataset_steps : list[int] or None
87
- Cumulative dataset boundaries for multi-dataset index remapping.
88
- None for single-dataset output.
87
+ Cumulative image counts per dataset, used to number cluster rows. Statistics rows are
88
+ numbered by steps recomputed from `calculation_results`. None for single-dataset output.
89
89
  """
90
90
 
91
91
  def __init__(
@@ -1752,7 +1752,8 @@ class Outliers(Evaluator):
1752
1752
  outliers_dfs: list[pl.DataFrame] = []
1753
1753
 
1754
1754
  if stats_results:
1755
- combined_stats, combined_source_index, _ = combine_stats_results(stats_results)
1755
+ # combined_steps count statistics rows, target rows included; dataset_steps count images, for cluster rows.
1756
+ combined_stats, combined_source_index, combined_steps = combine_stats_results(stats_results)
1756
1757
 
1757
1758
  class_ids: NDArray[np.intp] | None = None
1758
1759
  if per_class and metadata is not None:
@@ -1760,7 +1761,7 @@ class Outliers(Evaluator):
1760
1761
 
1761
1762
  outliers_df = self._get_outliers(combined_stats, combined_source_index, class_ids)
1762
1763
  outliers_df = drop_null_index_columns(outliers_df, ["target_index", "channel_index"])
1763
- outliers_df = add_dataset_index(outliers_df, dataset_steps)
1764
+ outliers_df = add_dataset_index(outliers_df, combined_steps)
1764
1765
  outliers_dfs.append(outliers_df)
1765
1766
 
1766
1767
  # Cluster-based: early fusion — combine all images, cluster globally
@@ -8,6 +8,7 @@ import sys
8
8
  from collections.abc import Callable, Iterable, Iterator, Mapping, Sequence
9
9
  from enum import Enum
10
10
  from importlib import import_module
11
+ from multiprocessing.pool import ThreadPool
11
12
  from os import cpu_count
12
13
  from types import ModuleType
13
14
  from typing import Any, Literal, TypeVar, cast, overload
@@ -948,9 +949,14 @@ class PoolWrapper:
948
949
  Also supports 'threads' for workloads where the GIL is released during computation.
949
950
  """
950
951
 
951
- def __init__(self, processes: int | None, context: Literal["fork", "spawn"] = DEFAULT_CONTEXT) -> None:
952
+ def __init__(self, processes: int | None, context: Literal["fork", "spawn", "threads"] = DEFAULT_CONTEXT) -> None:
952
953
  procs = 1 if processes is None else max(1, (cpu_count() or 1) + processes + 1) if processes < 0 else processes
953
- self._pool = multiprocessing.get_context(context).Pool(procs) if procs > 1 else None
954
+ if procs <= 1:
955
+ self._pool = None
956
+ elif context == "threads":
957
+ self._pool = ThreadPool(procs)
958
+ else:
959
+ self._pool = multiprocessing.get_context(context).Pool(procs)
954
960
 
955
961
  def imap_unordered(self, func: Callable[[T], R], iterable: Iterable[T]) -> Iterator[R]:
956
962
  """Apply `func` to each item in `iterable`, optionally using a pool."""
@@ -286,7 +286,7 @@ def to_bounding_box(boxlike: BoxLike, image_shape: tuple[int, ...] | None = None
286
286
  if isinstance(boxlike, Iterable):
287
287
  return BoundingBox(*boxlike, image_shape=image_shape)
288
288
  if isinstance(image_shape, tuple) and len(image_shape) > 2:
289
- return BoundingBox(0, 0, image_shape[-2], image_shape[-1], image_shape=image_shape)
289
+ return BoundingBox(0, 0, image_shape[-1], image_shape[-2], image_shape=image_shape)
290
290
  except (TypeError, ValueError):
291
291
  _logger.warning(f"Invalid bounding box format: {boxlike}. Expected a BoundingBox or a tuple/list of 4 numbers.")
292
292
 
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes