diffract-core 0.2.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.
Files changed (193) hide show
  1. diffract/__init__.py +52 -0
  2. diffract/configs/fast_speed_without_disk.ini +48 -0
  3. diffract/configs/hybrid.ini +74 -0
  4. diffract/configs/sqlite.ini +62 -0
  5. diffract/containers.py +405 -0
  6. diffract/core/__init__.py +23 -0
  7. diffract/core/cache/__init__.py +24 -0
  8. diffract/core/cache/containers.py +93 -0
  9. diffract/core/cache/interface.py +117 -0
  10. diffract/core/cache/redis_manager.py +464 -0
  11. diffract/core/cache/simple_manager.py +478 -0
  12. diffract/core/compute/__init__.py +46 -0
  13. diffract/core/compute/config.py +48 -0
  14. diffract/core/compute/containers.py +81 -0
  15. diffract/core/compute/decorator.py +125 -0
  16. diffract/core/compute/exceptions.py +31 -0
  17. diffract/core/compute/execution/__init__.py +14 -0
  18. diffract/core/compute/execution/_types.py +70 -0
  19. diffract/core/compute/execution/aggregation.py +74 -0
  20. diffract/core/compute/execution/aggregation_runner.py +362 -0
  21. diffract/core/compute/execution/enums.py +38 -0
  22. diffract/core/compute/execution/executor.py +125 -0
  23. diffract/core/compute/execution/parameter_runner.py +125 -0
  24. diffract/core/compute/execution/restrictions.py +61 -0
  25. diffract/core/compute/execution/strategy.py +118 -0
  26. diffract/core/compute/execution/utils.py +112 -0
  27. diffract/core/compute/extensions/__init__.py +0 -0
  28. diffract/core/compute/extensions/power_law.py +1051 -0
  29. diffract/core/compute/extensions/rmt.py +150 -0
  30. diffract/core/compute/extensions/utils.py +36 -0
  31. diffract/core/compute/field_signature.py +183 -0
  32. diffract/core/compute/kernels/__init__.py +48 -0
  33. diffract/core/compute/kernels/alignment.py +106 -0
  34. diffract/core/compute/kernels/heavy_tailed.py +394 -0
  35. diffract/core/compute/kernels/marchenko_pastur.py +99 -0
  36. diffract/core/compute/kernels/mat_decomposition.py +101 -0
  37. diffract/core/compute/kernels/mat_properties.py +53 -0
  38. diffract/core/compute/kernels/model_quality.py +27 -0
  39. diffract/core/compute/kernels/norms.py +88 -0
  40. diffract/core/compute/kernels/ranks.py +35 -0
  41. diffract/core/compute/kernels/tracy_widom.py +36 -0
  42. diffract/core/compute/metadata.py +67 -0
  43. diffract/core/compute/registry.py +485 -0
  44. diffract/core/constants.py +147 -0
  45. diffract/core/data/__init__.py +32 -0
  46. diffract/core/data/interface.py +304 -0
  47. diffract/core/data/metadata/__init__.py +15 -0
  48. diffract/core/data/metadata/containers.py +60 -0
  49. diffract/core/data/metadata/interface.py +208 -0
  50. diffract/core/data/metadata/sqlite_index.py +604 -0
  51. diffract/core/data/nn/__init__.py +43 -0
  52. diffract/core/data/nn/aggregates/__init__.py +35 -0
  53. diffract/core/data/nn/aggregates/metadata.py +96 -0
  54. diffract/core/data/nn/aggregates/proxy.py +57 -0
  55. diffract/core/data/nn/aggregates/repository.py +87 -0
  56. diffract/core/data/nn/aggregates/view.py +307 -0
  57. diffract/core/data/nn/containers.py +86 -0
  58. diffract/core/data/nn/extractors/__init__.py +49 -0
  59. diffract/core/data/nn/extractors/base.py +300 -0
  60. diffract/core/data/nn/extractors/factory.py +234 -0
  61. diffract/core/data/nn/extractors/flax.py +112 -0
  62. diffract/core/data/nn/extractors/handlers/__init__.py +39 -0
  63. diffract/core/data/nn/extractors/handlers/base.py +110 -0
  64. diffract/core/data/nn/extractors/handlers/flax_handlers.py +71 -0
  65. diffract/core/data/nn/extractors/handlers/numpy_handlers.py +63 -0
  66. diffract/core/data/nn/extractors/handlers/onnx_handlers.py +67 -0
  67. diffract/core/data/nn/extractors/handlers/tensorflow_handlers.py +82 -0
  68. diffract/core/data/nn/extractors/handlers/torch_handlers.py +124 -0
  69. diffract/core/data/nn/extractors/interface.py +56 -0
  70. diffract/core/data/nn/extractors/numpy.py +94 -0
  71. diffract/core/data/nn/extractors/onnx.py +108 -0
  72. diffract/core/data/nn/extractors/tensorflow.py +99 -0
  73. diffract/core/data/nn/extractors/torch.py +204 -0
  74. diffract/core/data/nn/params/__init__.py +27 -0
  75. diffract/core/data/nn/params/interface.py +402 -0
  76. diffract/core/data/nn/params/metadata.py +110 -0
  77. diffract/core/data/nn/params/proxy.py +93 -0
  78. diffract/core/data/nn/params/repository.py +45 -0
  79. diffract/core/data/nn/params/schema.py +82 -0
  80. diffract/core/data/nn/params/view.py +393 -0
  81. diffract/core/data/proxy.py +246 -0
  82. diffract/core/data/repository.py +227 -0
  83. diffract/core/data/utils.py +33 -0
  84. diffract/core/data/view.py +389 -0
  85. diffract/core/export/__init__.py +27 -0
  86. diffract/core/export/containers.py +47 -0
  87. diffract/core/export/exporters.py +191 -0
  88. diffract/core/export/formatters/__init__.py +23 -0
  89. diffract/core/export/formatters/base.py +68 -0
  90. diffract/core/export/formatters/dict_formatter.py +38 -0
  91. diffract/core/export/formatters/json_formatter.py +58 -0
  92. diffract/core/export/formatters/list_formatter.py +41 -0
  93. diffract/core/export/formatters/pandas_formatter.py +86 -0
  94. diffract/core/export/formatters/polars_formatter.py +86 -0
  95. diffract/core/export/formatters/registry.py +84 -0
  96. diffract/core/export/interface.py +105 -0
  97. diffract/core/parallel/__init__.py +21 -0
  98. diffract/core/parallel/containers.py +57 -0
  99. diffract/core/parallel/execution.py +91 -0
  100. diffract/core/parallel/runtime.py +91 -0
  101. diffract/core/storage/__init__.py +35 -0
  102. diffract/core/storage/base_manager.py +330 -0
  103. diffract/core/storage/containers.py +122 -0
  104. diffract/core/storage/hdf5_manager.py +856 -0
  105. diffract/core/storage/hybrid_manager.py +218 -0
  106. diffract/core/storage/interface.py +222 -0
  107. diffract/core/storage/metadata.py +89 -0
  108. diffract/core/storage/ram_manager.py +159 -0
  109. diffract/core/storage/sqlite_manager.py +1062 -0
  110. diffract/core/storage/zarr_manager.py +992 -0
  111. diffract/core/utils/__init__.py +45 -0
  112. diffract/core/utils/build.py +46 -0
  113. diffract/core/utils/exceptions.py +11 -0
  114. diffract/core/utils/hashing.py +90 -0
  115. diffract/core/utils/imports.py +292 -0
  116. diffract/core/utils/math.py +15 -0
  117. diffract/py.typed +0 -0
  118. diffract/session/__init__.py +24 -0
  119. diffract/session/errors.py +17 -0
  120. diffract/session/field_cache.py +216 -0
  121. diffract/session/namespaces/__init__.py +15 -0
  122. diffract/session/namespaces/compute/__init__.py +219 -0
  123. diffract/session/namespaces/models/__init__.py +282 -0
  124. diffract/session/namespaces/models/parameters/__init__.py +133 -0
  125. diffract/session/namespaces/models/parameters/meta_patcher.py +167 -0
  126. diffract/session/namespaces/results/__init__.py +378 -0
  127. diffract/session/namespaces/results/eraser.py +129 -0
  128. diffract/session/namespaces/results/injester.py +249 -0
  129. diffract/session/namespaces/utils/__init__.py +141 -0
  130. diffract/session/namespaces/utils/merger.py +295 -0
  131. diffract/session/namespaces/viz/__init__.py +91 -0
  132. diffract/session/namespaces/viz/_utils.py +14 -0
  133. diffract/session/namespaces/viz/box.py +207 -0
  134. diffract/session/namespaces/viz/grid.py +160 -0
  135. diffract/session/namespaces/viz/heatmap.py +164 -0
  136. diffract/session/namespaces/viz/scatter.py +202 -0
  137. diffract/session/namespaces/viz/sparkline.py +270 -0
  138. diffract/session/namespaces/viz/violin.py +212 -0
  139. diffract/session/session.py +260 -0
  140. diffract/session/utils.py +81 -0
  141. diffract/viz/__init__.py +42 -0
  142. diffract/viz/data/__init__.py +34 -0
  143. diffract/viz/data/detection.py +57 -0
  144. diffract/viz/data/extraction.py +117 -0
  145. diffract/viz/data/filtering.py +57 -0
  146. diffract/viz/data/ordering.py +129 -0
  147. diffract/viz/data/provider.py +99 -0
  148. diffract/viz/data/types.py +98 -0
  149. diffract/viz/plots/__init__.py +37 -0
  150. diffract/viz/plots/base/__init__.py +20 -0
  151. diffract/viz/plots/base/axis.py +219 -0
  152. diffract/viz/plots/base/coloraxis.py +133 -0
  153. diffract/viz/plots/base/configurator.py +18 -0
  154. diffract/viz/plots/base/jitter.py +368 -0
  155. diffract/viz/plots/base/line.py +197 -0
  156. diffract/viz/plots/base/marker.py +278 -0
  157. diffract/viz/plots/base/overlay.py +14 -0
  158. diffract/viz/plots/base/plot.py +110 -0
  159. diffract/viz/plots/base/update.py +50 -0
  160. diffract/viz/plots/boxplot.py +283 -0
  161. diffract/viz/plots/cluster.py +374 -0
  162. diffract/viz/plots/heatmap.py +168 -0
  163. diffract/viz/plots/scatter.py +233 -0
  164. diffract/viz/plots/sparkline.py +405 -0
  165. diffract/viz/plots/subplots/__init__.py +32 -0
  166. diffract/viz/plots/subplots/coloraxis.py +339 -0
  167. diffract/viz/plots/subplots/factory.py +713 -0
  168. diffract/viz/plots/subplots/grid.py +214 -0
  169. diffract/viz/plots/subplots/layout.py +370 -0
  170. diffract/viz/plots/subplots/spec.py +39 -0
  171. diffract/viz/plots/violin.py +298 -0
  172. diffract/viz/renderer.py +513 -0
  173. diffract/viz/styling/__init__.py +78 -0
  174. diffract/viz/styling/palettes/__init__.py +20 -0
  175. diffract/viz/styling/palettes/bundle.py +16 -0
  176. diffract/viz/styling/palettes/color.py +83 -0
  177. diffract/viz/styling/palettes/dashes.py +27 -0
  178. diffract/viz/styling/palettes/symbols.py +42 -0
  179. diffract/viz/styling/resolvers/__init__.py +11 -0
  180. diffract/viz/styling/resolvers/categorical.py +68 -0
  181. diffract/viz/styling/resolvers/color.py +77 -0
  182. diffract/viz/styling/resolvers/numeric.py +108 -0
  183. diffract/viz/styling/sources.py +27 -0
  184. diffract/viz/styling/theme/__init__.py +29 -0
  185. diffract/viz/styling/theme/applier.py +114 -0
  186. diffract/viz/styling/theme/components.py +66 -0
  187. diffract/viz/styling/theme/presets.py +58 -0
  188. diffract/viz/styling/theme/theme.py +36 -0
  189. diffract_core-0.2.1.dist-info/METADATA +530 -0
  190. diffract_core-0.2.1.dist-info/RECORD +193 -0
  191. diffract_core-0.2.1.dist-info/WHEEL +4 -0
  192. diffract_core-0.2.1.dist-info/licenses/LICENSE +201 -0
  193. diffract_core-0.2.1.dist-info/licenses/NOTICE +2 -0
@@ -0,0 +1,96 @@
1
+ """Metadata for aggregate entities.
2
+
3
+ This module provides the AggregateMetadata class for representing
4
+ aggregated data between parameters/models computed by aggregation kernels.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import json
10
+ from dataclasses import dataclass, field
11
+ from typing import Any, Self
12
+
13
+ from diffract.core.utils.hashing import get_unique_id
14
+
15
+
16
+ @dataclass(frozen=True, kw_only=True)
17
+ class AggregateMetadata:
18
+ """Immutable metadata container for aggregate entities.
19
+
20
+ An aggregate represents computed data involving multiple models or parameters,
21
+ such as overlap metrics between two models or correlation between parameters.
22
+
23
+ Attributes:
24
+ uid: Unique identifier automatically generated if not provided.
25
+ field_name: Base field name of the computed aggregate (e.g., "l_overlap").
26
+ context_models: Tuple of model IDs participating in this aggregate.
27
+ context_params: Tuple of parameter names participating in this aggregate.
28
+ """
29
+
30
+ uid: str = field(default_factory=get_unique_id)
31
+ field_name: str
32
+ context_models: tuple[str, ...] = ()
33
+ context_params: tuple[str, ...] = ()
34
+
35
+ def to_dict(self) -> dict[str, Any]:
36
+ """Serialize metadata to dictionary.
37
+
38
+ Returns:
39
+ Dictionary representation suitable for storage/reconstruction.
40
+ """
41
+ return {
42
+ "uid": self.uid,
43
+ "field_name": self.field_name,
44
+ "context_models": json.dumps(list(self.context_models)),
45
+ "context_params": json.dumps(list(self.context_params)),
46
+ }
47
+
48
+ @classmethod
49
+ def from_dict(cls, data: dict[str, Any]) -> Self:
50
+ """Deserialize metadata from dictionary.
51
+
52
+ Args:
53
+ data: Dictionary with metadata fields.
54
+
55
+ Returns:
56
+ AggregateMetadata instance.
57
+ """
58
+ # Handle both list format (from to_dict) and JSON string format (from index)
59
+ context_models = data.get("context_models", [])
60
+ if isinstance(context_models, str):
61
+ context_models = json.loads(context_models)
62
+
63
+ context_params = data.get("context_params", [])
64
+ if isinstance(context_params, str):
65
+ context_params = json.loads(context_params)
66
+
67
+ return cls(
68
+ uid=data["uid"],
69
+ field_name=data["field_name"],
70
+ context_models=tuple(context_models),
71
+ context_params=tuple(context_params),
72
+ )
73
+
74
+ @classmethod
75
+ def create_uid_from_context(
76
+ cls,
77
+ field_name: str,
78
+ context_models: tuple[str, ...],
79
+ context_params: tuple[str, ...],
80
+ ) -> str:
81
+ """Create a deterministic UID from the aggregate context.
82
+
83
+ This allows deduplication of aggregates with the same context.
84
+ Uses the same format as contextual field names in constants.py.
85
+
86
+ Args:
87
+ field_name: Base field name of the aggregate.
88
+ context_models: Tuple of model IDs.
89
+ context_params: Tuple of parameter names.
90
+
91
+ Returns:
92
+ A deterministic UID string based on the context.
93
+ """
94
+ from diffract.core.constants import format_contextual_field_name
95
+
96
+ return format_contextual_field_name(field_name, context_models, context_params)
@@ -0,0 +1,57 @@
1
+ """Proxy for aggregate entities.
2
+
3
+ This module provides the AggregateProxy class for accessing
4
+ aggregated data stored in the aggregates table.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from dataclasses import dataclass, field
10
+ from typing import TYPE_CHECKING
11
+
12
+ from diffract.core.constants import TABLE_AGGREGATES
13
+ from diffract.core.data.proxy import DataProxy
14
+
15
+ from .metadata import AggregateMetadata
16
+
17
+ if TYPE_CHECKING:
18
+ from .repository import AggregateRepository
19
+
20
+
21
+ @dataclass(kw_only=True)
22
+ class AggregateProxy(DataProxy[AggregateMetadata]):
23
+ """Lazy-loading proxy for aggregate data.
24
+
25
+ Extends the generic DataProxy with aggregate-specific configuration.
26
+ Aggregates are stored in the TABLE_AGGREGATES table and represent
27
+ computed aggregations between models/parameters.
28
+
29
+ Attributes:
30
+ meta: Immutable aggregate metadata.
31
+ _repository: Repository that owns storage/cache managers.
32
+ """
33
+
34
+ meta: AggregateMetadata
35
+ _repository: AggregateRepository = field(repr=False)
36
+
37
+ @classmethod
38
+ def get_table(cls) -> str:
39
+ """Return the storage table name for aggregates."""
40
+ return TABLE_AGGREGATES
41
+
42
+ @classmethod
43
+ def create_and_store(
44
+ cls,
45
+ meta: AggregateMetadata,
46
+ repository: AggregateRepository,
47
+ ) -> AggregateProxy:
48
+ """Create aggregate proxy and store metadata in index.
49
+
50
+ Args:
51
+ meta: Aggregate metadata.
52
+ repository: Repository owning storage, cache, and metadata managers.
53
+
54
+ Returns:
55
+ New aggregate proxy with metadata stored.
56
+ """
57
+ return super().create_and_store(meta=meta, repository=repository)
@@ -0,0 +1,87 @@
1
+ """Repository for aggregate entities.
2
+
3
+ This module provides the AggregateRepository class for managing
4
+ aggregate data storage and membership.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from typing import ClassVar
10
+
11
+ from diffract.core.constants import TABLE_AGGREGATES
12
+ from diffract.core.data.repository import DataRepository
13
+
14
+ from .metadata import AggregateMetadata
15
+ from .proxy import AggregateProxy
16
+ from .view import AggregateView
17
+
18
+
19
+ class AggregateRepository(DataRepository[AggregateMetadata, AggregateProxy]):
20
+ """Repository owning storage/cache/metadata and managing aggregate membership.
21
+
22
+ Extends the generic DataRepository with aggregate-specific configuration
23
+ for metadata class, proxy class, view class, storage table, and metadata schema.
24
+ """
25
+
26
+ METADATA_CLASS = AggregateMetadata
27
+ PROXY_CLASS = AggregateProxy
28
+ VIEW_CLASS = AggregateView
29
+ TABLE = TABLE_AGGREGATES
30
+
31
+ # Schema for MetadataIndex
32
+ METADATA_COLUMNS: ClassVar[dict[str, type]] = {
33
+ "field_name": str,
34
+ "context_models": str, # JSON-serialized tuple
35
+ "context_params": str, # JSON-serialized tuple
36
+ }
37
+ METADATA_INDEXES: ClassVar[list[str]] = ["field_name"]
38
+
39
+ def get_or_create(
40
+ self,
41
+ field_name: str,
42
+ context_models: tuple[str, ...],
43
+ context_params: tuple[str, ...],
44
+ ) -> AggregateProxy:
45
+ """Get existing aggregate by context or create a new one.
46
+
47
+ This method provides deduplication for aggregates with the same context.
48
+
49
+ Args:
50
+ field_name: Base field name of the aggregate.
51
+ context_models: Tuple of model IDs participating in this aggregate.
52
+ context_params: Tuple of parameter names participating in this aggregate.
53
+
54
+ Returns:
55
+ Existing or newly created AggregateProxy.
56
+ """
57
+ # Create deterministic UID
58
+ uid = AggregateMetadata.create_uid_from_context(
59
+ field_name=field_name,
60
+ context_models=context_models,
61
+ context_params=context_params,
62
+ )
63
+
64
+ # Check if already exists in cache or index
65
+ if uid in self._proxy_cache:
66
+ return self._proxy_cache[uid]
67
+
68
+ if self.has_uid(uid):
69
+ return self.get_proxy(uid)
70
+
71
+ # Create new aggregate
72
+ meta = AggregateMetadata(
73
+ uid=uid,
74
+ field_name=field_name,
75
+ context_models=context_models,
76
+ context_params=context_params,
77
+ )
78
+
79
+ return AggregateProxy.create_and_store(meta=meta, repository=self)
80
+
81
+ def create_view(self) -> AggregateView:
82
+ """Create a view over all aggregates in this repository.
83
+
84
+ Returns:
85
+ AggregateView containing all aggregates.
86
+ """
87
+ return AggregateView(repository=self, uids=None)
@@ -0,0 +1,307 @@
1
+ """View for aggregate entities.
2
+
3
+ This module provides the AggregateView class for batch operations
4
+ on filtered aggregate collections.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import re
10
+ from collections.abc import Iterator
11
+ from typing import TYPE_CHECKING
12
+
13
+ from diffract.core.constants import REGEX_PREFIX, TABLE_AGGREGATES
14
+ from diffract.core.data.interface import EntityUID
15
+ from diffract.core.data.utils import build_matcher
16
+ from diffract.core.data.view import DataView
17
+
18
+ from .metadata import AggregateMetadata
19
+ from .proxy import AggregateProxy
20
+
21
+ if TYPE_CHECKING:
22
+ from .repository import AggregateRepository
23
+
24
+
25
+ class AggregateView(DataView[AggregateMetadata, AggregateProxy]):
26
+ """A numpy-like view over a subset of aggregates owned by a repository.
27
+
28
+ Extends the generic DataView with aggregate-specific filtering methods.
29
+ Uses SQL-based filtering via MetadataIndex for efficiency.
30
+ """
31
+
32
+ def __init__(
33
+ self,
34
+ *,
35
+ repository: AggregateRepository,
36
+ uids: list[EntityUID] | None = None,
37
+ ) -> None:
38
+ super().__init__(repository=repository, uids=uids)
39
+
40
+ def __iter__(self) -> Iterator[AggregateProxy]:
41
+ """Iterate aggregate proxies in view order."""
42
+ return super().__iter__()
43
+
44
+ def _sort_in_place(self) -> None:
45
+ """Sort UIDs by field_name, context for deterministic ordering."""
46
+ uids = self._ensure_uids()
47
+ uids.sort(
48
+ key=lambda uid: (
49
+ self._repository.get_proxy(uid).meta.field_name,
50
+ ",".join(sorted(self._repository.get_proxy(uid).meta.context_models)),
51
+ ",".join(sorted(self._repository.get_proxy(uid).meta.context_params)),
52
+ uid,
53
+ )
54
+ )
55
+ self._sorted = True
56
+
57
+ def filter_by_field_name(
58
+ self, *names: str, inverse_mask: bool = False
59
+ ) -> AggregateView:
60
+ """Filter aggregates by field name.
61
+
62
+ Args:
63
+ *names: Field names to match. Use "re:" prefix for regex patterns.
64
+ inverse_mask: If True, return aggregates NOT matching the names.
65
+
66
+ Returns:
67
+ New view with filtered aggregates.
68
+ """
69
+ # Separate exact matches from regex patterns
70
+ exact_names: list[str] = []
71
+ regex_patterns: list[re.Pattern[str]] = []
72
+ for name in names:
73
+ if name.startswith(REGEX_PREFIX):
74
+ regex_patterns.append(re.compile(name.removeprefix(REGEX_PREFIX)))
75
+ else:
76
+ exact_names.append(name)
77
+
78
+ # If only exact matches and no inverse, use SQL
79
+ if exact_names and not regex_patterns and not inverse_mask:
80
+ current_uids = self._uids
81
+ if current_uids is None:
82
+ # Query directly from index
83
+ filtered = self._repository.metadata_index.query(
84
+ TABLE_AGGREGATES,
85
+ where_in={"field_name": exact_names},
86
+ )
87
+ else:
88
+ # Filter within current UIDs
89
+ filtered = self._repository.metadata_index.query(
90
+ TABLE_AGGREGATES,
91
+ where_in={"field_name": exact_names, "uid": current_uids},
92
+ )
93
+ return AggregateView(repository=self._repository, uids=filtered)
94
+
95
+ # Fall back to in-memory filtering for regex or inverse
96
+ if not self._sorted:
97
+ self._sort_in_place()
98
+
99
+ uids = self._ensure_uids()
100
+ matches = build_matcher(names)
101
+
102
+ if not inverse_mask:
103
+ filtered = [
104
+ uid
105
+ for uid in uids
106
+ if matches(self._repository.get_proxy(uid).meta.field_name)
107
+ ]
108
+ else:
109
+ filtered = [
110
+ uid
111
+ for uid in uids
112
+ if not matches(self._repository.get_proxy(uid).meta.field_name)
113
+ ]
114
+
115
+ return AggregateView(repository=self._repository, uids=filtered)
116
+
117
+ def filter_by_context_models(
118
+ self, *model_ids: str, require_all: bool = False
119
+ ) -> AggregateView:
120
+ """Filter aggregates by participating models.
121
+
122
+ Args:
123
+ *model_ids: Model IDs that must be in the aggregate's context_models.
124
+ require_all: If True, all model_ids must be present. If False,
125
+ at least one must be present.
126
+
127
+ Returns:
128
+ New view with filtered aggregates.
129
+ """
130
+ exact_names: set[str] = set()
131
+ regex_patterns: list[re.Pattern[str]] = []
132
+ for model_id in model_ids:
133
+ if model_id.startswith(REGEX_PREFIX):
134
+ regex_patterns.append(re.compile(model_id.removeprefix(REGEX_PREFIX)))
135
+ else:
136
+ exact_names.add(model_id)
137
+
138
+ if not self._sorted:
139
+ self._sort_in_place()
140
+
141
+ uids = self._ensure_uids()
142
+
143
+ def _matches(context_models: tuple[str, ...]) -> bool:
144
+ context_set = set(context_models)
145
+
146
+ if exact_names:
147
+ if require_all:
148
+ if not exact_names <= context_set:
149
+ return False
150
+ elif not (exact_names & context_set):
151
+ return False
152
+
153
+ if regex_patterns:
154
+ if require_all:
155
+ for pattern in regex_patterns:
156
+ if not any(
157
+ pattern.fullmatch(cm) is not None for cm in context_models
158
+ ):
159
+ return False
160
+ elif not any(
161
+ any(pattern.fullmatch(cm) is not None for pattern in regex_patterns)
162
+ for cm in context_models
163
+ ):
164
+ return False
165
+
166
+ return True
167
+
168
+ filtered = [
169
+ uid
170
+ for uid in uids
171
+ if _matches(self._repository.get_proxy(uid).meta.context_models)
172
+ ]
173
+
174
+ return AggregateView(repository=self._repository, uids=filtered)
175
+
176
+ def filter_by_context_params(
177
+ self, *param_names: str, require_all: bool = False
178
+ ) -> AggregateView:
179
+ """Filter aggregates by participating parameters.
180
+
181
+ Args:
182
+ *param_names: Parameter names that must be in the aggregate's
183
+ context_params.
184
+ require_all: If True, all param_names must be present. If False,
185
+ at least one must be present.
186
+
187
+ Returns:
188
+ New view with filtered aggregates.
189
+ """
190
+ exact_names: set[str] = set()
191
+ regex_patterns: list[re.Pattern[str]] = []
192
+ for param_name in param_names:
193
+ if param_name.startswith(REGEX_PREFIX):
194
+ regex_patterns.append(re.compile(param_name.removeprefix(REGEX_PREFIX)))
195
+ else:
196
+ exact_names.add(param_name)
197
+
198
+ if not self._sorted:
199
+ self._sort_in_place()
200
+
201
+ uids = self._ensure_uids()
202
+
203
+ def _matches(context_params: tuple[str, ...]) -> bool:
204
+ context_set = set(context_params)
205
+
206
+ if exact_names:
207
+ if require_all:
208
+ if not exact_names <= context_set:
209
+ return False
210
+ elif not (exact_names & context_set):
211
+ return False
212
+
213
+ if regex_patterns:
214
+ if require_all:
215
+ for pattern in regex_patterns:
216
+ if not any(
217
+ pattern.fullmatch(cp) is not None for cp in context_params
218
+ ):
219
+ return False
220
+ elif not any(
221
+ any(pattern.fullmatch(cp) is not None for pattern in regex_patterns)
222
+ for cp in context_params
223
+ ):
224
+ return False
225
+
226
+ return True
227
+
228
+ filtered = [
229
+ uid
230
+ for uid in uids
231
+ if _matches(self._repository.get_proxy(uid).meta.context_params)
232
+ ]
233
+
234
+ return AggregateView(repository=self._repository, uids=filtered)
235
+
236
+ def filter_by_exact_context(
237
+ self,
238
+ *,
239
+ models: tuple[str, ...] | None = None,
240
+ params: tuple[str, ...] | None = None,
241
+ ) -> AggregateView:
242
+ """Filter aggregates by exact context match.
243
+
244
+ Unlike filter_by_context_models/params which use set intersection,
245
+ this method requires exact equality of the context tuples.
246
+
247
+ Args:
248
+ models: Exact context_models tuple to match. If None, any models match.
249
+ params: Exact context_params tuple to match. If None, any params match.
250
+
251
+ Returns:
252
+ New view with aggregates matching the exact context.
253
+ """
254
+ if not self._sorted:
255
+ self._sort_in_place()
256
+
257
+ uids = self._ensure_uids()
258
+
259
+ def _matches(proxy: AggregateProxy) -> bool:
260
+ if models is not None and proxy.meta.context_models != models:
261
+ return False
262
+ return not (params is not None and proxy.meta.context_params != params)
263
+
264
+ filtered = [uid for uid in uids if _matches(self._repository.get_proxy(uid))]
265
+
266
+ return AggregateView(repository=self._repository, uids=filtered)
267
+
268
+ def erase_fields(self, *fields: str) -> None:
269
+ """Erase fields from all aggregates in this view."""
270
+ uids = self._ensure_uids()
271
+ if not uids:
272
+ return
273
+
274
+ with self:
275
+ for field in fields:
276
+ self._repository.storage_manager.erase_field_for_all(
277
+ field, table=TABLE_AGGREGATES
278
+ )
279
+ if self._repository.cache_manager is not None:
280
+ self._repository.cache_manager.erase_field_for_all(field)
281
+
282
+ def clear(self, erase: bool = False) -> None:
283
+ """Clear this view and optionally erase corresponding data.
284
+
285
+ Args:
286
+ erase: If True, also erase underlying storage data.
287
+ If False, only clear membership (metadata index).
288
+ """
289
+ uids = self._ensure_uids()
290
+
291
+ if erase and self._repository.cache_manager is not None:
292
+ self._repository.cache_manager.clear()
293
+
294
+ with self._repository:
295
+ for uid in list(uids):
296
+ self._repository._proxy_cache.pop(uid, None)
297
+ self._repository.metadata_index.delete(TABLE_AGGREGATES, uid)
298
+ if erase:
299
+ self._repository.storage_manager.erase_obj(
300
+ uid, table=TABLE_AGGREGATES
301
+ )
302
+
303
+ if self._uids is not None:
304
+ self._uids.clear()
305
+ else:
306
+ self._uids = []
307
+ self._sorted = True
@@ -0,0 +1,86 @@
1
+ """Dependency injection containers for model parameter management.
2
+
3
+ This module provides dependency injection configuration for model parameter
4
+ extraction and collection management using the dependency-injector library.
5
+ It integrates parameter extractors, storage managers, metadata index, and
6
+ cache managers for comprehensive parameter lifecycle management.
7
+
8
+ The container provides factory methods for creating parameter extractors
9
+ and initializing parameter collections, ensuring proper dependency
10
+ injection and configuration management.
11
+
12
+ Example:
13
+ >>> container = ModelParametersContainer()
14
+ >>> container.config.extractor.framework.from_value("pytorch")
15
+ >>> container.storage_manager.override(storage_instance)
16
+ >>> container.metadata_index.override(metadata_instance)
17
+ >>> container.cache_manager.override(cache_instance)
18
+ >>> collection = container.parameter_repository()
19
+ """
20
+
21
+ from __future__ import annotations
22
+
23
+ from dependency_injector import containers, providers
24
+
25
+ from diffract.core.data.metadata.interface import IMetadataIndex
26
+ from diffract.core.parallel import ParallelContext
27
+ from diffract.core.storage.interface import IStorageManager
28
+ from diffract.core.utils.build import build_with_defaults
29
+
30
+ from .aggregates.repository import AggregateRepository
31
+ from .extractors.factory import create_extractor
32
+ from .params.repository import ParameterRepository
33
+
34
+
35
+ class ModelParametersContainer(containers.DeclarativeContainer):
36
+ """Dependency injection container for model parameter components.
37
+
38
+ Provides comprehensive dependency injection setup for parameter extraction,
39
+ collection management, and data lifecycle operations. The container manages
40
+ the integration between parameter extractors, storage systems, metadata index,
41
+ and caching mechanisms.
42
+
43
+ The container uses external dependencies for storage, metadata index, and
44
+ cache managers, allowing flexible backend configuration while maintaining
45
+ consistent parameter extraction and collection interfaces.
46
+
47
+ Attributes:
48
+ config: Configuration provider for parameter extraction settings.
49
+ storage_manager: External dependency for persistent storage.
50
+ metadata_index: External dependency for structured metadata.
51
+ cache_manager: External dependency for temporary caching.
52
+ extractor_factory: Factory for creating parameter extractors.
53
+ parameter_repository: Singleton for parameter repository.
54
+ aggregate_repository: Singleton for aggregate repository.
55
+ """
56
+
57
+ config = providers.Configuration()
58
+
59
+ # External dependencies (injected from parent containers)
60
+ storage_manager = providers.Dependency(instance_of=IStorageManager)
61
+ metadata_index = providers.Dependency(instance_of=IMetadataIndex)
62
+ cache_manager = providers.Dependency()
63
+ parallel = providers.Dependency(instance_of=ParallelContext)
64
+
65
+ parameter_repository = providers.Singleton(
66
+ ParameterRepository.initialize,
67
+ storage_manager=storage_manager,
68
+ metadata_index=metadata_index,
69
+ cache_manager=cache_manager,
70
+ parallel=parallel,
71
+ )
72
+
73
+ aggregate_repository = providers.Singleton(
74
+ AggregateRepository.initialize,
75
+ storage_manager=storage_manager,
76
+ metadata_index=metadata_index,
77
+ cache_manager=cache_manager,
78
+ parallel=parallel,
79
+ )
80
+
81
+ # Parameter extractor factories
82
+ extractor_factory = providers.Factory(
83
+ build_with_defaults,
84
+ create_extractor,
85
+ config.extractor.as_(dict),
86
+ )
@@ -0,0 +1,49 @@
1
+ """Parameter extraction framework for neural network models.
2
+
3
+ This module provides a comprehensive framework for extracting parameters from
4
+ neural network models across different deep learning frameworks. It uses a
5
+ handler-based architecture for extensible and framework-specific parameter
6
+ processing.
7
+
8
+ Key Features:
9
+ - Framework-agnostic parameter extraction interface
10
+ - Handler-based processing for different parameter types
11
+ - Factory pattern for automatic extractor creation
12
+ - Override system for custom parameter metadata
13
+ - Extensible architecture for new frameworks and parameter types
14
+
15
+ Supported Frameworks:
16
+ - NumPy: dict[str, numpy.ndarray] mappings (no framework required)
17
+ - PyTorch: nn.Module and state_dict extraction
18
+ - Extensible design for additional frameworks
19
+
20
+ Example:
21
+ >>> from diffract.core.data.nn.extractors import create_extractor
22
+ >>> extractor = create_extractor(pytorch_model)
23
+ >>> parameters = extractor.extract_parameters(storage, cache)
24
+ """
25
+
26
+ from .base import BaseParameterExtractor, ExtractorOverrides, ParameterOverrides
27
+ from .factory import create_extractor, get_supported_frameworks, get_supported_types
28
+ from .flax import FlaxParamsExtractor
29
+ from .interface import IParameterExtractor
30
+ from .numpy import NumpyDictExtractor
31
+ from .onnx import OnnxModelExtractor
32
+ from .tensorflow import TensorFlowModelExtractor
33
+ from .torch import TorchModuleExtractor, TorchStateDictExtractor
34
+
35
+ __all__ = [
36
+ "BaseParameterExtractor",
37
+ "ExtractorOverrides",
38
+ "FlaxParamsExtractor",
39
+ "IParameterExtractor",
40
+ "NumpyDictExtractor",
41
+ "OnnxModelExtractor",
42
+ "ParameterOverrides",
43
+ "TensorFlowModelExtractor",
44
+ "TorchModuleExtractor",
45
+ "TorchStateDictExtractor",
46
+ "create_extractor",
47
+ "get_supported_frameworks",
48
+ "get_supported_types",
49
+ ]