dataeval-plots 0.0.11__tar.gz → 0.0.13__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.
- {dataeval_plots-0.0.11 → dataeval_plots-0.0.13}/PKG-INFO +3 -3
- {dataeval_plots-0.0.11 → dataeval_plots-0.0.13}/pyproject.toml +11 -3
- {dataeval_plots-0.0.11 → dataeval_plots-0.0.13}/src/dataeval_plots/__init__.py +40 -17
- {dataeval_plots-0.0.11 → dataeval_plots-0.0.13}/src/dataeval_plots/_version.py +2 -2
- {dataeval_plots-0.0.11 → dataeval_plots-0.0.13}/src/dataeval_plots/backends/_shared.py +58 -3
- {dataeval_plots-0.0.11 → dataeval_plots-0.0.13}/src/dataeval_plots/protocols.py +37 -16
- {dataeval_plots-0.0.11 → dataeval_plots-0.0.13}/.gitignore +0 -0
- {dataeval_plots-0.0.11 → dataeval_plots-0.0.13}/README.md +0 -0
- {dataeval_plots-0.0.11 → dataeval_plots-0.0.13}/src/dataeval_plots/_registry.py +0 -0
- {dataeval_plots-0.0.11 → dataeval_plots-0.0.13}/src/dataeval_plots/backends/__init__.py +0 -0
- {dataeval_plots-0.0.11 → dataeval_plots-0.0.13}/src/dataeval_plots/backends/_altair.py +0 -0
- {dataeval_plots-0.0.11 → dataeval_plots-0.0.13}/src/dataeval_plots/backends/_base.py +0 -0
- {dataeval_plots-0.0.11 → dataeval_plots-0.0.13}/src/dataeval_plots/backends/_feasibility_layout.py +0 -0
- {dataeval_plots-0.0.11 → dataeval_plots-0.0.13}/src/dataeval_plots/backends/_matplotlib.py +0 -0
- {dataeval_plots-0.0.11 → dataeval_plots-0.0.13}/src/dataeval_plots/backends/_plotly.py +0 -0
- {dataeval_plots-0.0.11 → dataeval_plots-0.0.13}/src/dataeval_plots/backends/_seaborn.py +0 -0
- {dataeval_plots-0.0.11 → dataeval_plots-0.0.13}/src/dataeval_plots/py.typed +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: dataeval-plots
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.13
|
|
4
4
|
Summary: DataEval companion package for plotting utilities
|
|
5
5
|
Project-URL: Homepage, https://dataeval.ai/
|
|
6
6
|
Project-URL: Repository, https://github.com/aria-ml/dataeval/
|
|
@@ -13,12 +13,12 @@ Classifier: Intended Audience :: Science/Research
|
|
|
13
13
|
Classifier: License :: OSI Approved :: MIT License
|
|
14
14
|
Classifier: Operating System :: OS Independent
|
|
15
15
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
16
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
17
16
|
Classifier: Programming Language :: Python :: 3.11
|
|
18
17
|
Classifier: Programming Language :: Python :: 3.12
|
|
19
18
|
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
20
20
|
Classifier: Topic :: Scientific/Engineering
|
|
21
|
-
Requires-Python: >=3.
|
|
21
|
+
Requires-Python: >=3.11
|
|
22
22
|
Requires-Dist: matplotlib>=3.7.1
|
|
23
23
|
Requires-Dist: numpy>=1.24.2; python_version < '3.12'
|
|
24
24
|
Requires-Dist: numpy>=1.26.2; python_version >= '3.12'
|
|
@@ -6,7 +6,7 @@ authors = [
|
|
|
6
6
|
{ name = "Andrew Weng", email = "andrew.weng@ariacoustics.com" },
|
|
7
7
|
{ name = "Ryan Wood", email = "ryan.wood@ariacoustics.com" },
|
|
8
8
|
]
|
|
9
|
-
requires-python = ">=3.
|
|
9
|
+
requires-python = ">=3.11"
|
|
10
10
|
readme = "README.md"
|
|
11
11
|
license = "MIT"
|
|
12
12
|
maintainers = [
|
|
@@ -18,10 +18,10 @@ classifiers = [
|
|
|
18
18
|
"Intended Audience :: Science/Research",
|
|
19
19
|
"License :: OSI Approved :: MIT License",
|
|
20
20
|
"Programming Language :: Python :: 3 :: Only",
|
|
21
|
-
"Programming Language :: Python :: 3.10",
|
|
22
21
|
"Programming Language :: Python :: 3.11",
|
|
23
22
|
"Programming Language :: Python :: 3.12",
|
|
24
23
|
"Programming Language :: Python :: 3.13",
|
|
24
|
+
"Programming Language :: Python :: 3.14",
|
|
25
25
|
"Topic :: Scientific/Engineering",
|
|
26
26
|
]
|
|
27
27
|
dependencies = [
|
|
@@ -86,6 +86,14 @@ dev = [
|
|
|
86
86
|
"ipywidgets",
|
|
87
87
|
]
|
|
88
88
|
|
|
89
|
+
[tool.uv]
|
|
90
|
+
constraint-dependencies = [
|
|
91
|
+
"pillow>=13.0.0", # Pillow 13.0.0 security release (decoder/encoder OOB reads and writes, DoS):
|
|
92
|
+
# CVE-2026-112395, CVE-2026-112397, CVE-2026-112400,
|
|
93
|
+
# CVE-2026-112403, CVE-2026-112404, CVE-2026-112895,
|
|
94
|
+
# CVE-2026-112896, CVE-2026-112897, CVE-2026-112899
|
|
95
|
+
]
|
|
96
|
+
|
|
89
97
|
[[tool.uv.index]]
|
|
90
98
|
name = "pytorch-cpu"
|
|
91
99
|
url = "https://download.pytorch.org/whl/cpu"
|
|
@@ -155,7 +163,7 @@ exclude = [
|
|
|
155
163
|
]
|
|
156
164
|
line-length = 120
|
|
157
165
|
indent-width = 4
|
|
158
|
-
target-version = "
|
|
166
|
+
target-version = "py311"
|
|
159
167
|
|
|
160
168
|
[tool.ruff.lint]
|
|
161
169
|
select = ["A", "ANN", "C4", "C90", "E", "F", "I", "NPY", "S", "SIM", "RET", "RUF100", "UP"]
|
|
@@ -198,7 +198,26 @@ def plot(
|
|
|
198
198
|
>>> plot(result, images=dataset) # Uses seaborn
|
|
199
199
|
"""
|
|
200
200
|
plotting_backend = get_backend(backend)
|
|
201
|
-
return plotting_backend.plot(output, figsize=figsize, **kwargs)
|
|
201
|
+
return _display_once(plotting_backend.plot(output, figsize=figsize, **kwargs))
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
def _display_once(result: Any) -> Any:
|
|
205
|
+
"""
|
|
206
|
+
Close a returned matplotlib figure under the notebook inline backend, so the notebook draws it once.
|
|
207
|
+
|
|
208
|
+
The inline backend draws every open pyplot figure when a cell ends, and the notebook draws a returned figure as
|
|
209
|
+
the cell's value, so an open returned figure appears twice. Closing it leaves the returned value as the only
|
|
210
|
+
drawing. Under any other backend the figure stays open for ``plt.show()``, and a list of figures is left open
|
|
211
|
+
because a notebook shows a list as text.
|
|
212
|
+
"""
|
|
213
|
+
import matplotlib
|
|
214
|
+
from matplotlib.figure import Figure
|
|
215
|
+
|
|
216
|
+
if isinstance(result, Figure) and "inline" in matplotlib.get_backend().lower():
|
|
217
|
+
import matplotlib.pyplot as plt
|
|
218
|
+
|
|
219
|
+
plt.close(result)
|
|
220
|
+
return result
|
|
202
221
|
|
|
203
222
|
|
|
204
223
|
def project(
|
|
@@ -319,14 +338,16 @@ def project(
|
|
|
319
338
|
)
|
|
320
339
|
for m in methods
|
|
321
340
|
]
|
|
322
|
-
return
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
341
|
+
return _display_once(
|
|
342
|
+
plotting_backend.project_grid(
|
|
343
|
+
reduced_list,
|
|
344
|
+
methods=methods,
|
|
345
|
+
labels=labels_array,
|
|
346
|
+
label_names=label_names,
|
|
347
|
+
dimensions=dimensions,
|
|
348
|
+
figsize=figsize,
|
|
349
|
+
title=title,
|
|
350
|
+
)
|
|
330
351
|
)
|
|
331
352
|
|
|
332
353
|
# Single method
|
|
@@ -347,12 +368,14 @@ def project(
|
|
|
347
368
|
)
|
|
348
369
|
dimensions = embeddings_array.shape[1] # type: ignore[assignment]
|
|
349
370
|
|
|
350
|
-
return
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
371
|
+
return _display_once(
|
|
372
|
+
plotting_backend.project(
|
|
373
|
+
embeddings_array,
|
|
374
|
+
labels=labels_array,
|
|
375
|
+
label_names=label_names,
|
|
376
|
+
method=method or "custom",
|
|
377
|
+
dimensions=dimensions,
|
|
378
|
+
figsize=figsize,
|
|
379
|
+
title=title,
|
|
380
|
+
)
|
|
358
381
|
)
|
|
@@ -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.0.
|
|
22
|
-
__version_tuple__ = version_tuple = (0, 0,
|
|
21
|
+
__version__ = version = '0.0.13'
|
|
22
|
+
__version_tuple__ = version_tuple = (0, 0, 13)
|
|
23
23
|
|
|
24
24
|
__commit_id__ = commit_id = None
|
|
@@ -167,8 +167,8 @@ def reduce_embeddings(
|
|
|
167
167
|
|
|
168
168
|
# scikit-learn 1.8 renamed the non-metric switch from `metric` to `metric_mds`
|
|
169
169
|
# -- `metric` now names the distance metric -- and moved `init` from fit() onto
|
|
170
|
-
# the constructor.
|
|
171
|
-
#
|
|
170
|
+
# the constructor. The projection extra still allows older releases, where neither
|
|
171
|
+
# new spelling exists.
|
|
172
172
|
#
|
|
173
173
|
# Ask the signature rather than compare version strings: it needs no extra
|
|
174
174
|
# dependency and tests exactly the thing being depended on. Omitting `init` on
|
|
@@ -932,6 +932,61 @@ def _feasibility_band(
|
|
|
932
932
|
)
|
|
933
933
|
|
|
934
934
|
|
|
935
|
+
# These mirror DataEval's performance/_feasibility.py: _SOURCES, _source_name, _unit_noun and FeasibilityOutput._bounds
|
|
936
|
+
_SOURCE_NAMES = {
|
|
937
|
+
"replica_ceiling/v1": "repeated labels",
|
|
938
|
+
"builtin_witness/v1:knn": "built-in k-NN",
|
|
939
|
+
"builtin_witness/v1:probe": "built-in linear probe",
|
|
940
|
+
"user_witness/v1": "your model",
|
|
941
|
+
}
|
|
942
|
+
_EVIDENCE_SCHEMA = {
|
|
943
|
+
"target_spec": pl.String,
|
|
944
|
+
"metric": pl.String,
|
|
945
|
+
"threshold": pl.Float64,
|
|
946
|
+
"source": pl.String,
|
|
947
|
+
"evidence_id": pl.String,
|
|
948
|
+
"information_scope": pl.String,
|
|
949
|
+
"unit": pl.String,
|
|
950
|
+
"bound_type": pl.String,
|
|
951
|
+
"observed": pl.Float64,
|
|
952
|
+
"bound": pl.Float64,
|
|
953
|
+
"n": pl.Int64,
|
|
954
|
+
"state": pl.String,
|
|
955
|
+
}
|
|
956
|
+
|
|
957
|
+
|
|
958
|
+
def _evidence_rows(output: PlottableFeasibility) -> pl.DataFrame:
|
|
959
|
+
"""One row per endpoint on a target in ``determinations``, in their order, then the order of ``evidence``."""
|
|
960
|
+
targets = {r["target_spec"]: r for r in output.determinations.iter_rows(named=True)}
|
|
961
|
+
rows = []
|
|
962
|
+
for spec, target in targets.items():
|
|
963
|
+
for eid, ev in output.evidence.items():
|
|
964
|
+
for e in ev.endpoints:
|
|
965
|
+
if e.target_spec != spec:
|
|
966
|
+
continue
|
|
967
|
+
stats = ev.details["endpoints"][spec] or {}
|
|
968
|
+
rows.append(
|
|
969
|
+
{
|
|
970
|
+
"target_spec": spec,
|
|
971
|
+
"metric": target["metric"],
|
|
972
|
+
"threshold": target["threshold"],
|
|
973
|
+
"source": _GROUP_CEILING
|
|
974
|
+
if ev.kind.startswith("local_panel_ceiling/v1")
|
|
975
|
+
else _SOURCE_NAMES.get(eid, eid),
|
|
976
|
+
"evidence_id": eid,
|
|
977
|
+
"information_scope": ev.information_scope,
|
|
978
|
+
"unit": "sequence" if ev.unit == "group" else "image",
|
|
979
|
+
"bound_type": e.direction,
|
|
980
|
+
# A ceiling's mean is panel agreement, not an observed score
|
|
981
|
+
"observed": stats.get("mean") if e.direction == "lower" else None,
|
|
982
|
+
"bound": e.value,
|
|
983
|
+
"n": stats.get("n"),
|
|
984
|
+
"state": e.state,
|
|
985
|
+
}
|
|
986
|
+
)
|
|
987
|
+
return pl.DataFrame(rows, schema=_EVIDENCE_SCHEMA)
|
|
988
|
+
|
|
989
|
+
|
|
935
990
|
def prepare_feasibility_data(output: PlottableFeasibility) -> list[FeasibilityBand]:
|
|
936
991
|
"""
|
|
937
992
|
Prepare feasibility data for plotting across all backends.
|
|
@@ -955,7 +1010,7 @@ def prepare_feasibility_data(output: PlottableFeasibility) -> list[FeasibilityBa
|
|
|
955
1010
|
spec = json.loads(row["target_spec"])
|
|
956
1011
|
spec.pop("threshold", None)
|
|
957
1012
|
groups.setdefault(json.dumps(spec, sort_keys=True), []).append(row)
|
|
958
|
-
evidence = output
|
|
1013
|
+
evidence = _evidence_rows(output).to_dicts()
|
|
959
1014
|
alpha = output.meta().state["alpha"]
|
|
960
1015
|
noun = _unit(rows, evidence) or "image" # the printout's footer noun, for the whole call
|
|
961
1016
|
bands = []
|
|
@@ -22,14 +22,16 @@ from datetime import datetime
|
|
|
22
22
|
from typing import (
|
|
23
23
|
Any,
|
|
24
24
|
Literal,
|
|
25
|
+
NotRequired,
|
|
25
26
|
Protocol,
|
|
27
|
+
Required,
|
|
26
28
|
TypedDict,
|
|
27
29
|
runtime_checkable,
|
|
28
30
|
)
|
|
29
31
|
|
|
30
32
|
import polars as pl
|
|
31
33
|
from numpy.typing import NDArray
|
|
32
|
-
from typing_extensions import
|
|
34
|
+
from typing_extensions import ReadOnly
|
|
33
35
|
|
|
34
36
|
|
|
35
37
|
class ExecutionMetadata(Protocol):
|
|
@@ -287,36 +289,55 @@ class PlottableDriftMVDC(Plottable, Protocol):
|
|
|
287
289
|
def plot_type(self) -> Literal["drift_mvdc"]: ...
|
|
288
290
|
|
|
289
291
|
|
|
292
|
+
class FeasibilityEndpoint(Protocol):
|
|
293
|
+
"""One bound on one target, as DataEval's ``Endpoint`` records it; only the fields the plot reads."""
|
|
294
|
+
|
|
295
|
+
@property
|
|
296
|
+
def target_spec(self) -> str: ...
|
|
297
|
+
@property
|
|
298
|
+
def value(self) -> float | None: ...
|
|
299
|
+
@property
|
|
300
|
+
def direction(self) -> Literal["lower", "upper"]: ...
|
|
301
|
+
@property
|
|
302
|
+
def state(self) -> str: ...
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
class FeasibilityEvidence(Protocol):
|
|
306
|
+
"""One evidence item, as DataEval's ``Evidence`` records it; only the fields the plot reads."""
|
|
307
|
+
|
|
308
|
+
@property
|
|
309
|
+
def kind(self) -> str: ...
|
|
310
|
+
@property
|
|
311
|
+
def information_scope(self) -> str: ...
|
|
312
|
+
@property
|
|
313
|
+
def unit(self) -> str: ...
|
|
314
|
+
@property
|
|
315
|
+
def endpoints(self) -> Sequence[FeasibilityEndpoint]: ...
|
|
316
|
+
@property
|
|
317
|
+
def details(self) -> Mapping[str, Any]: ...
|
|
318
|
+
|
|
319
|
+
|
|
290
320
|
@runtime_checkable
|
|
291
321
|
class PlottableFeasibility(Plottable, Protocol):
|
|
292
322
|
"""Protocol for feasibility plot outputs.
|
|
293
323
|
|
|
294
324
|
Required attributes:
|
|
295
325
|
- determinations: One row per target (DataFrame)
|
|
296
|
-
-
|
|
326
|
+
- evidence: Every evidence item of the call, by evidence id
|
|
297
327
|
- meta().state["alpha"]: The call's error budget
|
|
298
328
|
- plot_type -> 'feasibility'
|
|
299
329
|
|
|
300
|
-
|
|
330
|
+
Structures:
|
|
301
331
|
- determinations columns: target_spec, metric, threshold, judged_scope, determination, ceiling,
|
|
302
332
|
ceiling_scope, witness, witness_source
|
|
303
|
-
-
|
|
304
|
-
|
|
333
|
+
- each evidence item: kind, information_scope, unit (``item`` or ``group``), endpoints (target_spec, value,
|
|
334
|
+
direction, state) and details["endpoints"][target_spec], which is None or holds the bound's mean and n
|
|
305
335
|
"""
|
|
306
336
|
|
|
307
337
|
@property
|
|
308
338
|
def determinations(self) -> pl.DataFrame: ...
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
Returns
|
|
313
|
-
-------
|
|
314
|
-
pl.DataFrame
|
|
315
|
-
One row per evidence item and target: each source's bound on the target, and its observed score
|
|
316
|
-
where one exists
|
|
317
|
-
"""
|
|
318
|
-
...
|
|
319
|
-
|
|
339
|
+
@property
|
|
340
|
+
def evidence(self) -> Mapping[str, FeasibilityEvidence]: ...
|
|
320
341
|
@property
|
|
321
342
|
def plot_type(self) -> Literal["feasibility"]: ...
|
|
322
343
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dataeval_plots-0.0.11 → dataeval_plots-0.0.13}/src/dataeval_plots/backends/_feasibility_layout.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|