dataeval-flow 0.1.1__tar.gz → 0.1.2__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 (101) hide show
  1. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/.gitignore +3 -0
  2. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/PKG-INFO +1 -1
  3. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/pyproject.toml +3 -0
  4. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/_app/_model/_discover.py +20 -6
  5. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/_version.py +2 -2
  6. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/preprocessing.py +11 -4
  7. dataeval_flow-0.1.2/src/dataeval_flow/preprocessors.py +56 -0
  8. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/LICENSE +0 -0
  9. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/README.md +0 -0
  10. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/__init__.py +0 -0
  11. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/__main__.py +0 -0
  12. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/_app/__init__.py +0 -0
  13. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/_app/_model/__init__.py +0 -0
  14. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/_app/_model/_coerce.py +0 -0
  15. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/_app/_model/_execution.py +0 -0
  16. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/_app/_model/_introspect.py +0 -0
  17. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/_app/_model/_item.py +0 -0
  18. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/_app/_model/_registry.py +0 -0
  19. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/_app/_model/_state.py +0 -0
  20. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/_app/_model/_undo.py +0 -0
  21. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/_app/_panes/__init__.py +0 -0
  22. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/_app/_panes/_config_pane.py +0 -0
  23. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/_app/_panes/_result_pane.py +0 -0
  24. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/_app/_panes/_task_pane.py +0 -0
  25. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/_app/_panes/_widgets.py +0 -0
  26. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/_app/_screens/__init__.py +0 -0
  27. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/_app/_screens/_base.py +0 -0
  28. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/_app/_screens/_detail.py +0 -0
  29. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/_app/_screens/_model.py +0 -0
  30. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/_app/_screens/_params.py +0 -0
  31. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/_app/_screens/_pathpicker.py +0 -0
  32. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/_app/_screens/_section.py +0 -0
  33. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/_app/_screens/_settings.py +0 -0
  34. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/_app/_viewmodel/__init__.py +0 -0
  35. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/_app/_viewmodel/_builder_vm.py +0 -0
  36. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/_app/_viewmodel/_model_vm.py +0 -0
  37. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/_app/_viewmodel/_rendering.py +0 -0
  38. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/_app/_viewmodel/_result_vm.py +0 -0
  39. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/_app/_viewmodel/_section_vm.py +0 -0
  40. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/_app/app.py +0 -0
  41. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/_app/cli.py +0 -0
  42. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/_logging.py +0 -0
  43. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/cache.py +0 -0
  44. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/config/__init__.py +0 -0
  45. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/config/_loader.py +0 -0
  46. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/config/_merge.py +0 -0
  47. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/config/_models.py +0 -0
  48. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/config/_paths.py +0 -0
  49. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/config/schemas/__init__.py +0 -0
  50. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/config/schemas/_dataset.py +0 -0
  51. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/config/schemas/_extractor.py +0 -0
  52. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/config/schemas/_metadata.py +0 -0
  53. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/config/schemas/_preprocessor.py +0 -0
  54. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/config/schemas/_selection.py +0 -0
  55. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/config/schemas/_task.py +0 -0
  56. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/config/schemas/_workflow.py +0 -0
  57. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/dataset.py +0 -0
  58. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/embeddings.py +0 -0
  59. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/metadata.py +0 -0
  60. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/py.typed +0 -0
  61. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/runner.py +0 -0
  62. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/selection.py +0 -0
  63. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/workflow/__init__.py +0 -0
  64. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/workflow/_text_report.py +0 -0
  65. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/workflow/base.py +0 -0
  66. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/workflow/orchestrator.py +0 -0
  67. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/workflows/__init__.py +0 -0
  68. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/workflows/analysis/__init__.py +0 -0
  69. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/workflows/analysis/outputs.py +0 -0
  70. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/workflows/analysis/params.py +0 -0
  71. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/workflows/analysis/workflow.py +0 -0
  72. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/workflows/cleaning/__init__.py +0 -0
  73. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/workflows/cleaning/_internal.py +0 -0
  74. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/workflows/cleaning/outputs.py +0 -0
  75. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/workflows/cleaning/params.py +0 -0
  76. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/workflows/cleaning/report.py +0 -0
  77. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/workflows/cleaning/workflow.py +0 -0
  78. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/workflows/drift/__init__.py +0 -0
  79. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/workflows/drift/outputs.py +0 -0
  80. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/workflows/drift/params.py +0 -0
  81. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/workflows/drift/report.py +0 -0
  82. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/workflows/drift/workflow.py +0 -0
  83. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/workflows/ood/__init__.py +0 -0
  84. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/workflows/ood/outputs.py +0 -0
  85. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/workflows/ood/params.py +0 -0
  86. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/workflows/ood/report.py +0 -0
  87. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/workflows/ood/workflow.py +0 -0
  88. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/workflows/parameter_sweep/__init__.py +0 -0
  89. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/workflows/parameter_sweep/outputs.py +0 -0
  90. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/workflows/parameter_sweep/params.py +0 -0
  91. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/workflows/parameter_sweep/workflow.py +0 -0
  92. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/workflows/prioritization/__init__.py +0 -0
  93. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/workflows/prioritization/outputs.py +0 -0
  94. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/workflows/prioritization/params.py +0 -0
  95. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/workflows/prioritization/report.py +0 -0
  96. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/workflows/prioritization/workflow.py +0 -0
  97. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/workflows/splitting/__init__.py +0 -0
  98. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/workflows/splitting/outputs.py +0 -0
  99. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/workflows/splitting/params.py +0 -0
  100. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/workflows/splitting/report.py +0 -0
  101. {dataeval_flow-0.1.1 → dataeval_flow-0.1.2}/src/dataeval_flow/workflows/splitting/workflow.py +0 -0
@@ -34,6 +34,9 @@ output/
34
34
  # Generated notebooks (source of truth is MyST markdown)
35
35
  *.ipynb
36
36
 
37
+ # Jupyter execution cache (stored in docs-artifacts/<branch> orphan branch instead)
38
+ .jupyter_cache/
39
+
37
40
  # Nox
38
41
  .nox/
39
42
  .cuda-version
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dataeval-flow
3
- Version: 0.1.1
3
+ Version: 0.1.2
4
4
  Summary: DataEval Workflows container for data evaluation
5
5
  Project-URL: Repository, https://gitlab.jatic.net/jatic/aria/dataeval-flow
6
6
  License-Expression: MIT
@@ -257,6 +257,9 @@ output = "output/coverage.xml"
257
257
 
258
258
  [tool.pyright]
259
259
  reportMissingImports = false
260
+ # torch's stubs omit many runtime symbols (zeros, arange, equal, dtype, ...)
261
+ # from __all__, so pyright flags valid usage as private imports. Upstream defect.
262
+ reportPrivateImportUsage = false
260
263
 
261
264
  # --- Ruff [CR-3-G-2] ---
262
265
 
@@ -1,7 +1,8 @@
1
1
  """Runtime discovery of available transforms and selection classes.
2
2
 
3
- Introspects torchvision.transforms.v2 and dataeval.selection to provide
4
- dropdown options and parameter schemas for the builder TUI.
3
+ Introspects dataeval_flow.preprocessors, torchvision.transforms.v2, and
4
+ dataeval.selection to provide dropdown options and parameter schemas for the
5
+ builder TUI.
5
6
  """
6
7
 
7
8
  from __future__ import annotations
@@ -102,9 +103,16 @@ def _introspect_params(cls: type) -> list[ParamInfo]:
102
103
 
103
104
  @lru_cache(maxsize=1)
104
105
  def list_transforms() -> list[str]:
105
- """Return sorted names of available torchvision.transforms.v2 classes."""
106
+ """Return sorted names of available transforms.
107
+
108
+ Includes the custom named preprocessors (``dataeval_flow.preprocessors``)
109
+ alongside ``torchvision.transforms.v2`` classes, mirroring how
110
+ ``build_preprocessing`` resolves step names.
111
+ """
106
112
  from torchvision.transforms import v2
107
113
 
114
+ from dataeval_flow.preprocessors import CUSTOM_PREPROCESSORS
115
+
108
116
  skip = {
109
117
  "Transform",
110
118
  "Compose",
@@ -116,7 +124,7 @@ def list_transforms() -> list[str]:
116
124
  "InterpolationMode",
117
125
  "Lambda",
118
126
  }
119
- names = []
127
+ names = list(CUSTOM_PREPROCESSORS)
120
128
  for name, obj in inspect.getmembers(v2):
121
129
  if (
122
130
  inspect.isclass(obj)
@@ -151,10 +159,16 @@ def list_selection_classes() -> list[str]:
151
159
 
152
160
  @lru_cache(maxsize=64)
153
161
  def get_transform_params(name: str) -> list[ParamInfo]:
154
- """Get parameter info for a torchvision.transforms.v2 class."""
162
+ """Get parameter info for a transform.
163
+
164
+ Resolves custom preprocessors first, then ``torchvision.transforms.v2``,
165
+ matching ``build_preprocessing``'s resolution order.
166
+ """
155
167
  from torchvision.transforms import v2
156
168
 
157
- cls = getattr(v2, name, None)
169
+ from dataeval_flow.preprocessors import resolve_custom
170
+
171
+ cls = resolve_custom(name) or getattr(v2, name, None)
158
172
  if cls is None:
159
173
  return []
160
174
  return _introspect_params(cls)
@@ -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 = '0.1.1'
22
- __version_tuple__ = version_tuple = (0, 1, 1)
21
+ __version__ = version = '0.1.2'
22
+ __version_tuple__ = version_tuple = (0, 1, 2)
23
23
 
24
24
  __commit_id__ = commit_id = None
@@ -1,7 +1,9 @@
1
1
  """Preprocessing utilities for image transforms.
2
2
 
3
3
  Provides configuration-driven preprocessing using torchvision.transforms.v2.
4
- Any v2 transform can be specified by name in YAML config.
4
+ Any v2 transform can be specified by name in YAML config, plus the custom named
5
+ preprocessors in ``dataeval_flow.preprocessors`` (e.g. ``ToRGB``). Custom names
6
+ are resolved first but are distinct from torchvision names and never shadow them.
5
7
 
6
8
  The returned callable accepts a numpy CHW array, converts to a torch tensor
7
9
  for torchvision transforms, then converts back to a numpy CHW array so that
@@ -33,6 +35,7 @@ from numpy.typing import NDArray
33
35
  from pydantic import BaseModel, Field
34
36
 
35
37
  from dataeval_flow._logging import LogMessage
38
+ from dataeval_flow.preprocessors import CUSTOM_PREPROCESSORS, resolve_custom
36
39
 
37
40
  _logger: logging.Logger = logging.getLogger(__name__)
38
41
 
@@ -133,10 +136,14 @@ def build_preprocessing(steps: Sequence[PreprocessingStep]) -> _PreprocessingTra
133
136
  if key in params:
134
137
  params[key] = converter(params[key])
135
138
 
136
- # Get transform class and instantiate
137
- transform_cls = getattr(v2, step.step, None)
139
+ # Resolve custom preprocessors first, then torchvision. Custom names are
140
+ # distinct from torchvision names and never shadow them.
141
+ transform_cls = resolve_custom(step.step) or getattr(v2, step.step, None)
138
142
  if transform_cls is None:
139
- raise ValueError(f"Unknown transform: '{step.step}'. Check torchvision.transforms.v2 docs.")
143
+ raise ValueError(
144
+ f"Unknown transform: '{step.step}'. Must be a custom preprocessor "
145
+ f"({', '.join(CUSTOM_PREPROCESSORS)}) or a torchvision.transforms.v2 transform."
146
+ )
140
147
  ops.append(transform_cls(**params))
141
148
 
142
149
  composed = v2.Compose(ops)
@@ -0,0 +1,56 @@
1
+ """Custom named preprocessors resolved alongside torchvision transforms.
2
+
3
+ These supplement ``torchvision.transforms.v2``: ``build_preprocessing`` checks
4
+ this registry first, then falls back to torchvision. Custom preprocessors use
5
+ **distinct names** and do **not** shadow or override any torchvision ``v2``
6
+ transform — by design the names never collide.
7
+
8
+ Each preprocessor is a tensor -> tensor callable composed into ``v2.Compose``
9
+ exactly like a torchvision transform.
10
+ """
11
+
12
+ from typing import Any
13
+
14
+ __all__ = ["ToRGB", "CUSTOM_PREPROCESSORS", "resolve_custom"]
15
+
16
+
17
+ class ToRGB:
18
+ """Coerce a CHW tensor image to 3 channels (repeat grayscale, drop alpha).
19
+
20
+ torchvision's ``v2.RGB`` expands 1->3 channels but leaves 4-channel RGBA
21
+ untouched, so models expecting 3-channel input still fail on RGBA inputs.
22
+ This handles both: 1/2-channel -> repeat luma to RGB, >=4-channel -> keep
23
+ the first three (drop alpha); 3-channel passes through. The stable ``repr``
24
+ keeps the preprocessing cache key deterministic.
25
+ """
26
+
27
+ __slots__ = ()
28
+
29
+ def __call__(self, image: Any) -> Any:
30
+ """Coerce a CHW (or HW) tensor image to exactly 3 channels."""
31
+ if image.ndim == 2: # HW -> 1HW
32
+ image = image.unsqueeze(0)
33
+ channels = image.shape[0]
34
+ if channels == 3:
35
+ return image
36
+ if channels > 3: # RGBA (or more) -> drop alpha/extra channels
37
+ return image[:3]
38
+ return image[:1].repeat(3, 1, 1) # gray (or gray+alpha) -> RGB
39
+
40
+ def __repr__(self) -> str:
41
+ """Return a deterministic repr for preprocessing cache-key stability."""
42
+ return "ToRGB()"
43
+
44
+
45
+ # Registry of custom preprocessors. Names here MUST be distinct from torchvision
46
+ # v2 transform names — custom preprocessors never shadow/override torchvision.
47
+ CUSTOM_PREPROCESSORS: dict[str, type] = {"ToRGB": ToRGB}
48
+
49
+
50
+ def resolve_custom(name: str) -> type | None:
51
+ """Return the registered custom preprocessor class for ``name``, else ``None``.
52
+
53
+ A ``None`` result signals the caller to fall back to torchvision. Custom
54
+ names do not shadow torchvision transforms; the two name spaces are disjoint.
55
+ """
56
+ return CUSTOM_PREPROCESSORS.get(name)
File without changes
File without changes