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.
- diffract/__init__.py +52 -0
- diffract/configs/fast_speed_without_disk.ini +48 -0
- diffract/configs/hybrid.ini +74 -0
- diffract/configs/sqlite.ini +62 -0
- diffract/containers.py +405 -0
- diffract/core/__init__.py +23 -0
- diffract/core/cache/__init__.py +24 -0
- diffract/core/cache/containers.py +93 -0
- diffract/core/cache/interface.py +117 -0
- diffract/core/cache/redis_manager.py +464 -0
- diffract/core/cache/simple_manager.py +478 -0
- diffract/core/compute/__init__.py +46 -0
- diffract/core/compute/config.py +48 -0
- diffract/core/compute/containers.py +81 -0
- diffract/core/compute/decorator.py +125 -0
- diffract/core/compute/exceptions.py +31 -0
- diffract/core/compute/execution/__init__.py +14 -0
- diffract/core/compute/execution/_types.py +70 -0
- diffract/core/compute/execution/aggregation.py +74 -0
- diffract/core/compute/execution/aggregation_runner.py +362 -0
- diffract/core/compute/execution/enums.py +38 -0
- diffract/core/compute/execution/executor.py +125 -0
- diffract/core/compute/execution/parameter_runner.py +125 -0
- diffract/core/compute/execution/restrictions.py +61 -0
- diffract/core/compute/execution/strategy.py +118 -0
- diffract/core/compute/execution/utils.py +112 -0
- diffract/core/compute/extensions/__init__.py +0 -0
- diffract/core/compute/extensions/power_law.py +1051 -0
- diffract/core/compute/extensions/rmt.py +150 -0
- diffract/core/compute/extensions/utils.py +36 -0
- diffract/core/compute/field_signature.py +183 -0
- diffract/core/compute/kernels/__init__.py +48 -0
- diffract/core/compute/kernels/alignment.py +106 -0
- diffract/core/compute/kernels/heavy_tailed.py +394 -0
- diffract/core/compute/kernels/marchenko_pastur.py +99 -0
- diffract/core/compute/kernels/mat_decomposition.py +101 -0
- diffract/core/compute/kernels/mat_properties.py +53 -0
- diffract/core/compute/kernels/model_quality.py +27 -0
- diffract/core/compute/kernels/norms.py +88 -0
- diffract/core/compute/kernels/ranks.py +35 -0
- diffract/core/compute/kernels/tracy_widom.py +36 -0
- diffract/core/compute/metadata.py +67 -0
- diffract/core/compute/registry.py +485 -0
- diffract/core/constants.py +147 -0
- diffract/core/data/__init__.py +32 -0
- diffract/core/data/interface.py +304 -0
- diffract/core/data/metadata/__init__.py +15 -0
- diffract/core/data/metadata/containers.py +60 -0
- diffract/core/data/metadata/interface.py +208 -0
- diffract/core/data/metadata/sqlite_index.py +604 -0
- diffract/core/data/nn/__init__.py +43 -0
- diffract/core/data/nn/aggregates/__init__.py +35 -0
- diffract/core/data/nn/aggregates/metadata.py +96 -0
- diffract/core/data/nn/aggregates/proxy.py +57 -0
- diffract/core/data/nn/aggregates/repository.py +87 -0
- diffract/core/data/nn/aggregates/view.py +307 -0
- diffract/core/data/nn/containers.py +86 -0
- diffract/core/data/nn/extractors/__init__.py +49 -0
- diffract/core/data/nn/extractors/base.py +300 -0
- diffract/core/data/nn/extractors/factory.py +234 -0
- diffract/core/data/nn/extractors/flax.py +112 -0
- diffract/core/data/nn/extractors/handlers/__init__.py +39 -0
- diffract/core/data/nn/extractors/handlers/base.py +110 -0
- diffract/core/data/nn/extractors/handlers/flax_handlers.py +71 -0
- diffract/core/data/nn/extractors/handlers/numpy_handlers.py +63 -0
- diffract/core/data/nn/extractors/handlers/onnx_handlers.py +67 -0
- diffract/core/data/nn/extractors/handlers/tensorflow_handlers.py +82 -0
- diffract/core/data/nn/extractors/handlers/torch_handlers.py +124 -0
- diffract/core/data/nn/extractors/interface.py +56 -0
- diffract/core/data/nn/extractors/numpy.py +94 -0
- diffract/core/data/nn/extractors/onnx.py +108 -0
- diffract/core/data/nn/extractors/tensorflow.py +99 -0
- diffract/core/data/nn/extractors/torch.py +204 -0
- diffract/core/data/nn/params/__init__.py +27 -0
- diffract/core/data/nn/params/interface.py +402 -0
- diffract/core/data/nn/params/metadata.py +110 -0
- diffract/core/data/nn/params/proxy.py +93 -0
- diffract/core/data/nn/params/repository.py +45 -0
- diffract/core/data/nn/params/schema.py +82 -0
- diffract/core/data/nn/params/view.py +393 -0
- diffract/core/data/proxy.py +246 -0
- diffract/core/data/repository.py +227 -0
- diffract/core/data/utils.py +33 -0
- diffract/core/data/view.py +389 -0
- diffract/core/export/__init__.py +27 -0
- diffract/core/export/containers.py +47 -0
- diffract/core/export/exporters.py +191 -0
- diffract/core/export/formatters/__init__.py +23 -0
- diffract/core/export/formatters/base.py +68 -0
- diffract/core/export/formatters/dict_formatter.py +38 -0
- diffract/core/export/formatters/json_formatter.py +58 -0
- diffract/core/export/formatters/list_formatter.py +41 -0
- diffract/core/export/formatters/pandas_formatter.py +86 -0
- diffract/core/export/formatters/polars_formatter.py +86 -0
- diffract/core/export/formatters/registry.py +84 -0
- diffract/core/export/interface.py +105 -0
- diffract/core/parallel/__init__.py +21 -0
- diffract/core/parallel/containers.py +57 -0
- diffract/core/parallel/execution.py +91 -0
- diffract/core/parallel/runtime.py +91 -0
- diffract/core/storage/__init__.py +35 -0
- diffract/core/storage/base_manager.py +330 -0
- diffract/core/storage/containers.py +122 -0
- diffract/core/storage/hdf5_manager.py +856 -0
- diffract/core/storage/hybrid_manager.py +218 -0
- diffract/core/storage/interface.py +222 -0
- diffract/core/storage/metadata.py +89 -0
- diffract/core/storage/ram_manager.py +159 -0
- diffract/core/storage/sqlite_manager.py +1062 -0
- diffract/core/storage/zarr_manager.py +992 -0
- diffract/core/utils/__init__.py +45 -0
- diffract/core/utils/build.py +46 -0
- diffract/core/utils/exceptions.py +11 -0
- diffract/core/utils/hashing.py +90 -0
- diffract/core/utils/imports.py +292 -0
- diffract/core/utils/math.py +15 -0
- diffract/py.typed +0 -0
- diffract/session/__init__.py +24 -0
- diffract/session/errors.py +17 -0
- diffract/session/field_cache.py +216 -0
- diffract/session/namespaces/__init__.py +15 -0
- diffract/session/namespaces/compute/__init__.py +219 -0
- diffract/session/namespaces/models/__init__.py +282 -0
- diffract/session/namespaces/models/parameters/__init__.py +133 -0
- diffract/session/namespaces/models/parameters/meta_patcher.py +167 -0
- diffract/session/namespaces/results/__init__.py +378 -0
- diffract/session/namespaces/results/eraser.py +129 -0
- diffract/session/namespaces/results/injester.py +249 -0
- diffract/session/namespaces/utils/__init__.py +141 -0
- diffract/session/namespaces/utils/merger.py +295 -0
- diffract/session/namespaces/viz/__init__.py +91 -0
- diffract/session/namespaces/viz/_utils.py +14 -0
- diffract/session/namespaces/viz/box.py +207 -0
- diffract/session/namespaces/viz/grid.py +160 -0
- diffract/session/namespaces/viz/heatmap.py +164 -0
- diffract/session/namespaces/viz/scatter.py +202 -0
- diffract/session/namespaces/viz/sparkline.py +270 -0
- diffract/session/namespaces/viz/violin.py +212 -0
- diffract/session/session.py +260 -0
- diffract/session/utils.py +81 -0
- diffract/viz/__init__.py +42 -0
- diffract/viz/data/__init__.py +34 -0
- diffract/viz/data/detection.py +57 -0
- diffract/viz/data/extraction.py +117 -0
- diffract/viz/data/filtering.py +57 -0
- diffract/viz/data/ordering.py +129 -0
- diffract/viz/data/provider.py +99 -0
- diffract/viz/data/types.py +98 -0
- diffract/viz/plots/__init__.py +37 -0
- diffract/viz/plots/base/__init__.py +20 -0
- diffract/viz/plots/base/axis.py +219 -0
- diffract/viz/plots/base/coloraxis.py +133 -0
- diffract/viz/plots/base/configurator.py +18 -0
- diffract/viz/plots/base/jitter.py +368 -0
- diffract/viz/plots/base/line.py +197 -0
- diffract/viz/plots/base/marker.py +278 -0
- diffract/viz/plots/base/overlay.py +14 -0
- diffract/viz/plots/base/plot.py +110 -0
- diffract/viz/plots/base/update.py +50 -0
- diffract/viz/plots/boxplot.py +283 -0
- diffract/viz/plots/cluster.py +374 -0
- diffract/viz/plots/heatmap.py +168 -0
- diffract/viz/plots/scatter.py +233 -0
- diffract/viz/plots/sparkline.py +405 -0
- diffract/viz/plots/subplots/__init__.py +32 -0
- diffract/viz/plots/subplots/coloraxis.py +339 -0
- diffract/viz/plots/subplots/factory.py +713 -0
- diffract/viz/plots/subplots/grid.py +214 -0
- diffract/viz/plots/subplots/layout.py +370 -0
- diffract/viz/plots/subplots/spec.py +39 -0
- diffract/viz/plots/violin.py +298 -0
- diffract/viz/renderer.py +513 -0
- diffract/viz/styling/__init__.py +78 -0
- diffract/viz/styling/palettes/__init__.py +20 -0
- diffract/viz/styling/palettes/bundle.py +16 -0
- diffract/viz/styling/palettes/color.py +83 -0
- diffract/viz/styling/palettes/dashes.py +27 -0
- diffract/viz/styling/palettes/symbols.py +42 -0
- diffract/viz/styling/resolvers/__init__.py +11 -0
- diffract/viz/styling/resolvers/categorical.py +68 -0
- diffract/viz/styling/resolvers/color.py +77 -0
- diffract/viz/styling/resolvers/numeric.py +108 -0
- diffract/viz/styling/sources.py +27 -0
- diffract/viz/styling/theme/__init__.py +29 -0
- diffract/viz/styling/theme/applier.py +114 -0
- diffract/viz/styling/theme/components.py +66 -0
- diffract/viz/styling/theme/presets.py +58 -0
- diffract/viz/styling/theme/theme.py +36 -0
- diffract_core-0.2.1.dist-info/METADATA +530 -0
- diffract_core-0.2.1.dist-info/RECORD +193 -0
- diffract_core-0.2.1.dist-info/WHEEL +4 -0
- diffract_core-0.2.1.dist-info/licenses/LICENSE +201 -0
- diffract_core-0.2.1.dist-info/licenses/NOTICE +2 -0
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"""Domain schema definitions for diffract.core.data.nn.
|
|
2
|
+
|
|
3
|
+
This module centralizes NN-domain type aliases and enumerations to keep
|
|
4
|
+
interfaces explicit and avoid ambiguous bare primitives like str/int in
|
|
5
|
+
public APIs. It defines the core domain schema including parameter types,
|
|
6
|
+
identifiers, and field names.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from enum import IntFlag, auto
|
|
12
|
+
|
|
13
|
+
# Domain primitives.
|
|
14
|
+
type ParameterUID = str
|
|
15
|
+
"""Unique identifier of a parameter in storage."""
|
|
16
|
+
|
|
17
|
+
type ParameterIndex = int
|
|
18
|
+
"""Zero-based positional index within a view or list-like ordering."""
|
|
19
|
+
|
|
20
|
+
type FieldName = str
|
|
21
|
+
"""Field name for parameter-associated data stored in backends (e.g., "weights")."""
|
|
22
|
+
|
|
23
|
+
type ModelID = str
|
|
24
|
+
"""Unique identifier of a model containing parameters."""
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class ParameterType(IntFlag):
|
|
28
|
+
"""Parameter type enumeration with extensible design.
|
|
29
|
+
|
|
30
|
+
This enumeration supports bitwise operations for flexible parameter
|
|
31
|
+
filtering and type combination. New parameter types can be added
|
|
32
|
+
dynamically through string conversion, making it extensible for
|
|
33
|
+
future parameter classifications.
|
|
34
|
+
|
|
35
|
+
The IntFlag base allows combining types using bitwise OR operations
|
|
36
|
+
and checking membership using bitwise AND operations.
|
|
37
|
+
|
|
38
|
+
Attributes:
|
|
39
|
+
UNKNOWN: Default type for unclassified parameters.
|
|
40
|
+
DENSE: Dense/fully-connected layer parameters.
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
UNKNOWN = 0
|
|
44
|
+
DENSE = auto()
|
|
45
|
+
|
|
46
|
+
@classmethod
|
|
47
|
+
def from_string(cls, type_str: str) -> ParameterType:
|
|
48
|
+
"""Create parameter type from string representation.
|
|
49
|
+
|
|
50
|
+
Attempts to match existing parameter types first, then creates
|
|
51
|
+
new dynamic types for unknown strings. This allows the system
|
|
52
|
+
to adapt to new parameter types without code changes.
|
|
53
|
+
|
|
54
|
+
Args:
|
|
55
|
+
type_str: String representation of parameter type.
|
|
56
|
+
|
|
57
|
+
Returns:
|
|
58
|
+
Corresponding ParameterType enum value.
|
|
59
|
+
"""
|
|
60
|
+
try:
|
|
61
|
+
return cls[type_str.upper()]
|
|
62
|
+
except KeyError:
|
|
63
|
+
# Create dynamic parameter type for new types
|
|
64
|
+
current_max = max(cls._value2member_map_.values())
|
|
65
|
+
new_value = 1 << (current_max.bit_length())
|
|
66
|
+
return cls._create_custom_type(type_str.upper(), new_value)
|
|
67
|
+
|
|
68
|
+
@classmethod
|
|
69
|
+
def _create_custom_type(cls, name: str, value: int) -> ParameterType:
|
|
70
|
+
"""Create a custom parameter type dynamically."""
|
|
71
|
+
new_member = int.__new__(cls, value)
|
|
72
|
+
new_member._name_ = name
|
|
73
|
+
new_member._value_ = value
|
|
74
|
+
|
|
75
|
+
cls._member_map_[name] = new_member
|
|
76
|
+
cls._value2member_map_[value] = new_member
|
|
77
|
+
|
|
78
|
+
return new_member
|
|
79
|
+
|
|
80
|
+
def __repr__(self) -> str:
|
|
81
|
+
"""Return string representation of parameter type."""
|
|
82
|
+
return self.name
|
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
"""Parameter view for batch operations on filtered parameter collections.
|
|
2
|
+
|
|
3
|
+
This module provides the ParameterView class that extends the generic DataView
|
|
4
|
+
with parameter-specific filtering methods.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import logging
|
|
10
|
+
import re
|
|
11
|
+
from collections.abc import Iterator
|
|
12
|
+
from typing import TYPE_CHECKING
|
|
13
|
+
|
|
14
|
+
import numpy as np
|
|
15
|
+
|
|
16
|
+
from diffract.core.constants import REGEX_PREFIX, TABLE_PARAMETERS
|
|
17
|
+
from diffract.core.data.utils import build_matcher
|
|
18
|
+
from diffract.core.data.view import DataView
|
|
19
|
+
from diffract.core.parallel import ParallelContext, map_maybe_parallel
|
|
20
|
+
|
|
21
|
+
from .metadata import ParameterMetadata
|
|
22
|
+
from .proxy import ParameterDataProxy
|
|
23
|
+
from .schema import FieldName, ModelID, ParameterType, ParameterUID
|
|
24
|
+
|
|
25
|
+
if TYPE_CHECKING:
|
|
26
|
+
from .interface import IParameterProxy, IParameterRepository
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
logger = logging.getLogger(__name__)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class ParameterView(DataView[ParameterMetadata, ParameterDataProxy]):
|
|
33
|
+
"""A numpy-like view over a subset of parameters owned by a repository.
|
|
34
|
+
|
|
35
|
+
Extends the generic DataView with parameter-specific filtering methods
|
|
36
|
+
such as filter_by_name, filter_by_ptype, and filter_by_model_id.
|
|
37
|
+
Uses SQL-based filtering via MetadataIndex for efficiency.
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
def __init__(
|
|
41
|
+
self,
|
|
42
|
+
*,
|
|
43
|
+
repository: IParameterRepository,
|
|
44
|
+
uids: list[ParameterUID] | None = None,
|
|
45
|
+
) -> None:
|
|
46
|
+
super().__init__(repository=repository, uids=uids)
|
|
47
|
+
|
|
48
|
+
def __iter__(self) -> Iterator[IParameterProxy]:
|
|
49
|
+
"""Iterate parameter proxies in view order."""
|
|
50
|
+
return super().__iter__()
|
|
51
|
+
|
|
52
|
+
def _sort_in_place(self) -> None:
|
|
53
|
+
"""Sort UIDs by model_id, name, then uid for deterministic ordering."""
|
|
54
|
+
uids = self._ensure_uids()
|
|
55
|
+
uids.sort(
|
|
56
|
+
key=lambda uid: (
|
|
57
|
+
self._repository.get_proxy(uid).meta.model_id,
|
|
58
|
+
self._repository.get_proxy(uid).meta.name,
|
|
59
|
+
uid,
|
|
60
|
+
)
|
|
61
|
+
)
|
|
62
|
+
self._sorted = True
|
|
63
|
+
|
|
64
|
+
def filter_by_name(self, *names: str, inverse_mask: bool = False) -> ParameterView:
|
|
65
|
+
"""Filter parameters by name.
|
|
66
|
+
|
|
67
|
+
Args:
|
|
68
|
+
*names: Parameter names to match. Use "re:" prefix for regex patterns.
|
|
69
|
+
inverse_mask: If True, return parameters NOT matching the names.
|
|
70
|
+
|
|
71
|
+
Returns:
|
|
72
|
+
New view with filtered parameters.
|
|
73
|
+
"""
|
|
74
|
+
# Separate exact matches from regex patterns
|
|
75
|
+
exact_names: list[str] = []
|
|
76
|
+
regex_patterns: list[re.Pattern[str]] = []
|
|
77
|
+
for name in names:
|
|
78
|
+
if name.startswith(REGEX_PREFIX):
|
|
79
|
+
regex_patterns.append(re.compile(name.removeprefix(REGEX_PREFIX)))
|
|
80
|
+
else:
|
|
81
|
+
exact_names.append(name)
|
|
82
|
+
|
|
83
|
+
# If only exact matches and no inverse, use SQL
|
|
84
|
+
if exact_names and not regex_patterns and not inverse_mask:
|
|
85
|
+
current_uids = self._uids
|
|
86
|
+
if current_uids is None:
|
|
87
|
+
# Query directly from index
|
|
88
|
+
filtered = self._repository.metadata_index.query(
|
|
89
|
+
TABLE_PARAMETERS,
|
|
90
|
+
where_in={"name": exact_names},
|
|
91
|
+
)
|
|
92
|
+
else:
|
|
93
|
+
# Filter within current UIDs
|
|
94
|
+
filtered = self._repository.metadata_index.query(
|
|
95
|
+
TABLE_PARAMETERS,
|
|
96
|
+
where_in={"name": exact_names, "uid": current_uids},
|
|
97
|
+
)
|
|
98
|
+
return ParameterView(repository=self._repository, uids=filtered)
|
|
99
|
+
|
|
100
|
+
# Fall back to in-memory filtering for regex or inverse
|
|
101
|
+
if not self._sorted:
|
|
102
|
+
self._sort_in_place()
|
|
103
|
+
|
|
104
|
+
uids = self._ensure_uids()
|
|
105
|
+
matches = build_matcher(names)
|
|
106
|
+
|
|
107
|
+
if not inverse_mask:
|
|
108
|
+
filtered = [
|
|
109
|
+
uid
|
|
110
|
+
for uid in uids
|
|
111
|
+
if matches(self._repository.get_proxy(uid).meta.name)
|
|
112
|
+
]
|
|
113
|
+
else:
|
|
114
|
+
filtered = [
|
|
115
|
+
uid
|
|
116
|
+
for uid in uids
|
|
117
|
+
if not matches(self._repository.get_proxy(uid).meta.name)
|
|
118
|
+
]
|
|
119
|
+
|
|
120
|
+
return ParameterView(repository=self._repository, uids=filtered)
|
|
121
|
+
|
|
122
|
+
def filter_by_ptype(self, *ptypes: str | ParameterType) -> ParameterView:
|
|
123
|
+
"""Filter parameters by parameter type.
|
|
124
|
+
|
|
125
|
+
Args:
|
|
126
|
+
*ptypes: Parameter types to include (strings or ParameterType values).
|
|
127
|
+
|
|
128
|
+
Returns:
|
|
129
|
+
New view with filtered parameters.
|
|
130
|
+
"""
|
|
131
|
+
# Convert to string names for SQL query
|
|
132
|
+
ptype_names: list[str] = []
|
|
133
|
+
for ptype in ptypes:
|
|
134
|
+
if isinstance(ptype, ParameterType):
|
|
135
|
+
ptype_names.append(ptype.name)
|
|
136
|
+
else:
|
|
137
|
+
ptype_names.append(ptype.upper())
|
|
138
|
+
|
|
139
|
+
current_uids = self._uids
|
|
140
|
+
if current_uids is None:
|
|
141
|
+
# Query directly from index
|
|
142
|
+
filtered = self._repository.metadata_index.query(
|
|
143
|
+
TABLE_PARAMETERS,
|
|
144
|
+
where_in={"ptype": ptype_names},
|
|
145
|
+
)
|
|
146
|
+
else:
|
|
147
|
+
# Filter within current UIDs
|
|
148
|
+
filtered = self._repository.metadata_index.query(
|
|
149
|
+
TABLE_PARAMETERS,
|
|
150
|
+
where_in={"ptype": ptype_names, "uid": current_uids},
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
return ParameterView(repository=self._repository, uids=filtered)
|
|
154
|
+
|
|
155
|
+
def filter_by_model_id(
|
|
156
|
+
self, *model_ids: ModelID, inverse_mask: bool = False
|
|
157
|
+
) -> ParameterView:
|
|
158
|
+
"""Filter parameters by model id.
|
|
159
|
+
|
|
160
|
+
Args:
|
|
161
|
+
*model_ids: Model IDs to match. Use "re:" prefix for regex patterns.
|
|
162
|
+
inverse_mask: If True, return parameters NOT matching the model IDs.
|
|
163
|
+
|
|
164
|
+
Returns:
|
|
165
|
+
New view with filtered parameters.
|
|
166
|
+
"""
|
|
167
|
+
# Separate exact matches from regex patterns
|
|
168
|
+
exact_ids: list[str] = []
|
|
169
|
+
regex_patterns: list[re.Pattern[str]] = []
|
|
170
|
+
for model_id in model_ids:
|
|
171
|
+
if model_id.startswith(REGEX_PREFIX):
|
|
172
|
+
regex_patterns.append(re.compile(model_id.removeprefix(REGEX_PREFIX)))
|
|
173
|
+
else:
|
|
174
|
+
exact_ids.append(model_id)
|
|
175
|
+
|
|
176
|
+
# If only exact matches and no inverse, use SQL
|
|
177
|
+
if exact_ids and not regex_patterns and not inverse_mask:
|
|
178
|
+
current_uids = self._uids
|
|
179
|
+
if current_uids is None:
|
|
180
|
+
# Query directly from index
|
|
181
|
+
filtered = self._repository.metadata_index.query(
|
|
182
|
+
TABLE_PARAMETERS,
|
|
183
|
+
where_in={"model_id": exact_ids},
|
|
184
|
+
)
|
|
185
|
+
else:
|
|
186
|
+
# Filter within current UIDs
|
|
187
|
+
filtered = self._repository.metadata_index.query(
|
|
188
|
+
TABLE_PARAMETERS,
|
|
189
|
+
where_in={"model_id": exact_ids, "uid": current_uids},
|
|
190
|
+
)
|
|
191
|
+
return ParameterView(repository=self._repository, uids=filtered)
|
|
192
|
+
|
|
193
|
+
# Fall back to in-memory filtering for regex or inverse
|
|
194
|
+
if not self._sorted:
|
|
195
|
+
self._sort_in_place()
|
|
196
|
+
|
|
197
|
+
uids = self._ensure_uids()
|
|
198
|
+
matches = build_matcher(model_ids)
|
|
199
|
+
|
|
200
|
+
if not inverse_mask:
|
|
201
|
+
filtered = [
|
|
202
|
+
uid
|
|
203
|
+
for uid in uids
|
|
204
|
+
if matches(self._repository.get_proxy(uid).meta.model_id)
|
|
205
|
+
]
|
|
206
|
+
else:
|
|
207
|
+
filtered = [
|
|
208
|
+
uid
|
|
209
|
+
for uid in uids
|
|
210
|
+
if not matches(self._repository.get_proxy(uid).meta.model_id)
|
|
211
|
+
]
|
|
212
|
+
|
|
213
|
+
return ParameterView(repository=self._repository, uids=filtered)
|
|
214
|
+
|
|
215
|
+
def filter_by_fields(
|
|
216
|
+
self,
|
|
217
|
+
*fields: FieldName,
|
|
218
|
+
inverse_mask: bool = False,
|
|
219
|
+
parallel: ParallelContext | None = None,
|
|
220
|
+
) -> ParameterView:
|
|
221
|
+
"""Filter parameters by the presence of one or more fields.
|
|
222
|
+
|
|
223
|
+
Args:
|
|
224
|
+
*fields: Field names that must be present.
|
|
225
|
+
inverse_mask: If True, return parameters WITHOUT the specified fields.
|
|
226
|
+
parallel: Optional parallel context for concurrent checks.
|
|
227
|
+
|
|
228
|
+
Returns:
|
|
229
|
+
New view with filtered parameters.
|
|
230
|
+
"""
|
|
231
|
+
result = super().filter_by_fields(
|
|
232
|
+
*fields, inverse_mask=inverse_mask, parallel=parallel
|
|
233
|
+
)
|
|
234
|
+
return ParameterView(repository=self._repository, uids=result._uids)
|
|
235
|
+
|
|
236
|
+
def iter_chunks_by_read_budget(
|
|
237
|
+
self,
|
|
238
|
+
*,
|
|
239
|
+
budget_bytes: int | None = None,
|
|
240
|
+
required_fields_by_uid: dict[ParameterUID, list[FieldName]],
|
|
241
|
+
default_field_bytes: int = 1024 * 1024,
|
|
242
|
+
parallel: ParallelContext | None = None,
|
|
243
|
+
) -> Iterator[ParameterView]:
|
|
244
|
+
"""Yield sub-views chunked by approximate read budget.
|
|
245
|
+
|
|
246
|
+
Args:
|
|
247
|
+
budget_bytes: Maximum bytes per chunk. If None, auto-detects from
|
|
248
|
+
cache_manager.get_available_bytes() with 40% headroom factor.
|
|
249
|
+
required_fields_by_uid: Mapping of uid -> required fields to include
|
|
250
|
+
in the estimate.
|
|
251
|
+
default_field_bytes: Fallback size estimate when metadata is missing.
|
|
252
|
+
parallel: Optional parallel context for metadata estimation.
|
|
253
|
+
"""
|
|
254
|
+
if not self._sorted:
|
|
255
|
+
self._sort_in_place()
|
|
256
|
+
|
|
257
|
+
uids = self._ensure_uids()
|
|
258
|
+
if not uids:
|
|
259
|
+
return
|
|
260
|
+
|
|
261
|
+
if budget_bytes is None:
|
|
262
|
+
budget_bytes = self._get_cache_budget_bytes()
|
|
263
|
+
|
|
264
|
+
if budget_bytes <= 0:
|
|
265
|
+
yield self
|
|
266
|
+
return
|
|
267
|
+
|
|
268
|
+
def _estimate_field_bytes(uid: ParameterUID, field: FieldName) -> int:
|
|
269
|
+
meta = self._repository.get_proxy(uid).get_field_metadata(field)
|
|
270
|
+
if not meta:
|
|
271
|
+
return default_field_bytes
|
|
272
|
+
|
|
273
|
+
shape = meta.get("shape")
|
|
274
|
+
dtype = meta.get("dtype")
|
|
275
|
+
if not shape or not dtype:
|
|
276
|
+
return default_field_bytes
|
|
277
|
+
|
|
278
|
+
try:
|
|
279
|
+
itemsize = int(np.dtype(dtype).itemsize)
|
|
280
|
+
n = 1
|
|
281
|
+
for x in shape:
|
|
282
|
+
n *= int(x)
|
|
283
|
+
return max(1, n * itemsize)
|
|
284
|
+
except Exception: # noqa: BLE001
|
|
285
|
+
return default_field_bytes
|
|
286
|
+
|
|
287
|
+
def _estimate_uid(uid: ParameterUID) -> int:
|
|
288
|
+
fields = required_fields_by_uid.get(uid, [])
|
|
289
|
+
if not fields:
|
|
290
|
+
return 0
|
|
291
|
+
return sum(_estimate_field_bytes(uid, f) for f in fields)
|
|
292
|
+
|
|
293
|
+
estimates = map_maybe_parallel(uids, _estimate_uid, parallel=parallel)
|
|
294
|
+
uid_to_est = dict(zip(uids, estimates, strict=True))
|
|
295
|
+
|
|
296
|
+
chunk: list[ParameterUID] = []
|
|
297
|
+
used = 0
|
|
298
|
+
for uid in uids:
|
|
299
|
+
estimated_bytes = uid_to_est[uid]
|
|
300
|
+
if chunk and (used + estimated_bytes > budget_bytes):
|
|
301
|
+
yield ParameterView(repository=self._repository, uids=list(chunk))
|
|
302
|
+
chunk.clear()
|
|
303
|
+
used = 0
|
|
304
|
+
chunk.append(uid)
|
|
305
|
+
used += estimated_bytes
|
|
306
|
+
if chunk:
|
|
307
|
+
yield ParameterView(repository=self._repository, uids=chunk)
|
|
308
|
+
|
|
309
|
+
def erase_fields(self, *fields: FieldName) -> None:
|
|
310
|
+
"""Erase fields from all parameters in this view."""
|
|
311
|
+
uids = self._ensure_uids()
|
|
312
|
+
if not uids:
|
|
313
|
+
return
|
|
314
|
+
|
|
315
|
+
with self:
|
|
316
|
+
for uid in uids:
|
|
317
|
+
for field in fields:
|
|
318
|
+
self._repository.storage_manager.erase_field(
|
|
319
|
+
uid, field, table=TABLE_PARAMETERS
|
|
320
|
+
)
|
|
321
|
+
if self._repository.cache_manager is not None:
|
|
322
|
+
self._repository.cache_manager.erase_field(uid, field)
|
|
323
|
+
|
|
324
|
+
def erase_fields_with_regexp(self, *patterns: str) -> None:
|
|
325
|
+
"""Erase fields matching regex patterns from all parameters in this view."""
|
|
326
|
+
uids = self._ensure_uids()
|
|
327
|
+
if not uids:
|
|
328
|
+
return
|
|
329
|
+
|
|
330
|
+
all_fields = set(
|
|
331
|
+
self._repository.storage_manager.list_fields(table=TABLE_PARAMETERS)
|
|
332
|
+
)
|
|
333
|
+
|
|
334
|
+
with self:
|
|
335
|
+
for uid in uids:
|
|
336
|
+
for pattern in patterns:
|
|
337
|
+
for field_name in all_fields:
|
|
338
|
+
if re.fullmatch(pattern, field_name):
|
|
339
|
+
self._repository.storage_manager.erase_field(
|
|
340
|
+
uid, field_name, table=TABLE_PARAMETERS
|
|
341
|
+
)
|
|
342
|
+
if self._repository.cache_manager is not None:
|
|
343
|
+
self._repository.cache_manager.erase_field(
|
|
344
|
+
uid, field_name
|
|
345
|
+
)
|
|
346
|
+
|
|
347
|
+
def clear(self, erase: bool = False) -> None:
|
|
348
|
+
"""Clear this view and optionally erase corresponding data.
|
|
349
|
+
|
|
350
|
+
Args:
|
|
351
|
+
erase: If True, also erase underlying storage data.
|
|
352
|
+
If False, only clear membership (metadata index).
|
|
353
|
+
"""
|
|
354
|
+
uids = self._ensure_uids()
|
|
355
|
+
|
|
356
|
+
if erase and self._repository.cache_manager is not None:
|
|
357
|
+
self._repository.cache_manager.clear()
|
|
358
|
+
|
|
359
|
+
with self._repository:
|
|
360
|
+
for uid in list(uids):
|
|
361
|
+
self._repository._proxy_cache.pop(uid, None)
|
|
362
|
+
self._repository.metadata_index.delete(TABLE_PARAMETERS, uid)
|
|
363
|
+
if erase:
|
|
364
|
+
self._repository.storage_manager.erase_obj(
|
|
365
|
+
uid, table=TABLE_PARAMETERS
|
|
366
|
+
)
|
|
367
|
+
|
|
368
|
+
if self._uids is not None:
|
|
369
|
+
self._uids.clear()
|
|
370
|
+
else:
|
|
371
|
+
self._uids = []
|
|
372
|
+
self._sorted = True
|
|
373
|
+
|
|
374
|
+
def _get_cache_budget_bytes(self, headroom_factor: float = 0.4) -> int:
|
|
375
|
+
"""Get read budget based on available cache capacity.
|
|
376
|
+
|
|
377
|
+
Args:
|
|
378
|
+
headroom_factor: Fraction of available cache to use (default 40%).
|
|
379
|
+
|
|
380
|
+
Returns:
|
|
381
|
+
Budget in bytes, or fallback value if cache unavailable.
|
|
382
|
+
"""
|
|
383
|
+
fallback = 256 * 1024 * 1024 # 256MB
|
|
384
|
+
|
|
385
|
+
cache = self._repository.cache_manager
|
|
386
|
+
if cache is None:
|
|
387
|
+
return fallback
|
|
388
|
+
|
|
389
|
+
available = cache.get_available_bytes()
|
|
390
|
+
if available is None:
|
|
391
|
+
return fallback
|
|
392
|
+
|
|
393
|
+
return max(1024 * 1024, int(available * headroom_factor))
|