dataeval-plots 0.0.1__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.1/.gitignore +21 -0
- dataeval_plots-0.0.1/PKG-INFO +229 -0
- dataeval_plots-0.0.1/README.md +190 -0
- dataeval_plots-0.0.1/pyproject.toml +146 -0
- dataeval_plots-0.0.1/src/dataeval_plots/__init__.py +56 -0
- dataeval_plots-0.0.1/src/dataeval_plots/_registry.py +103 -0
- dataeval_plots-0.0.1/src/dataeval_plots/_version.py +34 -0
- dataeval_plots-0.0.1/src/dataeval_plots/backends/__init__.py +7 -0
- dataeval_plots-0.0.1/src/dataeval_plots/backends/_altair.py +698 -0
- dataeval_plots-0.0.1/src/dataeval_plots/backends/_base.py +172 -0
- dataeval_plots-0.0.1/src/dataeval_plots/backends/_matplotlib.py +767 -0
- dataeval_plots-0.0.1/src/dataeval_plots/backends/_plotly.py +714 -0
- dataeval_plots-0.0.1/src/dataeval_plots/backends/_seaborn.py +541 -0
- dataeval_plots-0.0.1/src/dataeval_plots/backends/_shared.py +96 -0
- dataeval_plots-0.0.1/src/dataeval_plots/protocols.py +267 -0
- dataeval_plots-0.0.1/src/dataeval_plots/py.typed +0 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
*venv*/
|
|
2
|
+
__pycache__/
|
|
3
|
+
dist/
|
|
4
|
+
|
|
5
|
+
docs/build/
|
|
6
|
+
docs/source/reference/autoapi
|
|
7
|
+
docs/source/tutorials/notebooks/checkpoints/
|
|
8
|
+
|
|
9
|
+
output/
|
|
10
|
+
.coverage*
|
|
11
|
+
|
|
12
|
+
.nox/
|
|
13
|
+
.python-version
|
|
14
|
+
|
|
15
|
+
# Used to store user customizable settings
|
|
16
|
+
.settings
|
|
17
|
+
|
|
18
|
+
# debug profiles
|
|
19
|
+
.vscode/launch.json
|
|
20
|
+
|
|
21
|
+
src/dataeval_plots/_version.py
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: dataeval-plots
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: DataEval companion package for plotting utilities
|
|
5
|
+
Project-URL: Homepage, https://dataeval.ai/
|
|
6
|
+
Project-URL: Repository, https://github.com/aria-ml/dataeval/
|
|
7
|
+
Project-URL: Documentation, https://dataeval.readthedocs.io/
|
|
8
|
+
Author-email: Andrew Weng <andrew.weng@ariacoustics.com>, Ryan Wood <ryan.wood@ariacoustics.com>, Shaun Jullens <shaun.jullens@ariacoustics.com>
|
|
9
|
+
Maintainer-email: ARiA <dataeval@ariacoustics.com>
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Science/Research
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Topic :: Scientific/Engineering
|
|
21
|
+
Requires-Python: <3.14,>=3.10
|
|
22
|
+
Requires-Dist: numpy<2.3,>=1.24.2; python_version < '3.12'
|
|
23
|
+
Requires-Dist: numpy<2.3,>=1.26.2; python_version >= '3.12'
|
|
24
|
+
Provides-Extra: all
|
|
25
|
+
Requires-Dist: altair>=5.0; extra == 'all'
|
|
26
|
+
Requires-Dist: matplotlib>=3.7.1; extra == 'all'
|
|
27
|
+
Requires-Dist: plotly>=5.0; extra == 'all'
|
|
28
|
+
Requires-Dist: seaborn>=0.12; extra == 'all'
|
|
29
|
+
Provides-Extra: altair
|
|
30
|
+
Requires-Dist: altair>=5.0; extra == 'altair'
|
|
31
|
+
Provides-Extra: matplotlib
|
|
32
|
+
Requires-Dist: matplotlib>=3.7.1; extra == 'matplotlib'
|
|
33
|
+
Provides-Extra: plotly
|
|
34
|
+
Requires-Dist: plotly>=5.0; extra == 'plotly'
|
|
35
|
+
Provides-Extra: seaborn
|
|
36
|
+
Requires-Dist: matplotlib>=3.7.1; extra == 'seaborn'
|
|
37
|
+
Requires-Dist: seaborn>=0.12; extra == 'seaborn'
|
|
38
|
+
Description-Content-Type: text/markdown
|
|
39
|
+
|
|
40
|
+
# DataEval Plots
|
|
41
|
+
|
|
42
|
+
Multi-backend plotting utilities for DataEval outputs.
|
|
43
|
+
|
|
44
|
+
## Installation
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
# Minimal - no plotting backend included
|
|
48
|
+
pip install dataeval-plots
|
|
49
|
+
|
|
50
|
+
# With matplotlib plotting (recommended)
|
|
51
|
+
pip install dataeval-plots[matplotlib]
|
|
52
|
+
|
|
53
|
+
# With multiple backends
|
|
54
|
+
pip install dataeval-plots[matplotlib,plotly]
|
|
55
|
+
|
|
56
|
+
# Everything
|
|
57
|
+
pip install dataeval-plots[all]
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
For development:
|
|
61
|
+
```bash
|
|
62
|
+
pip install -e dataeval-plots[all]
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Available Backends
|
|
66
|
+
|
|
67
|
+
| Backend | Status | Install With | Description |
|
|
68
|
+
|---------|--------|--------------|-------------|
|
|
69
|
+
| matplotlib | ✅ Default | `[matplotlib]` | Standard publication-quality plots |
|
|
70
|
+
| seaborn | ✅ Available | `[seaborn]` | Statistical data visualization |
|
|
71
|
+
| plotly | ✅ Available | `[plotly]` | Interactive web-based plots |
|
|
72
|
+
| altair | ✅ Available | `[altair]` | Declarative visualization grammar |
|
|
73
|
+
|
|
74
|
+
## Usage
|
|
75
|
+
|
|
76
|
+
### Option 1: Import from dataeval-plots directly
|
|
77
|
+
|
|
78
|
+
```python
|
|
79
|
+
from dataeval_plots import plot
|
|
80
|
+
from dataeval.metrics.bias import coverage
|
|
81
|
+
|
|
82
|
+
result = coverage(embeddings)
|
|
83
|
+
fig = plot(result, images=dataset, top_k=6)
|
|
84
|
+
fig.savefig("coverage.png")
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Option 2: Import from dataeval core (convenience)
|
|
88
|
+
|
|
89
|
+
```python
|
|
90
|
+
from dataeval import plotting
|
|
91
|
+
from dataeval.metrics.bias import coverage
|
|
92
|
+
|
|
93
|
+
result = coverage(embeddings)
|
|
94
|
+
fig = plotting.plot(result, images=dataset)
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Option 3: Set default backend
|
|
98
|
+
|
|
99
|
+
```python
|
|
100
|
+
from dataeval_plots import plot, set_default_backend
|
|
101
|
+
|
|
102
|
+
# Set seaborn as default
|
|
103
|
+
set_default_backend("seaborn")
|
|
104
|
+
fig = plot(result, images=dataset) # Uses seaborn
|
|
105
|
+
|
|
106
|
+
# Override for a specific plot
|
|
107
|
+
fig = plot(result, backend="matplotlib", images=dataset)
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Features
|
|
111
|
+
|
|
112
|
+
- **Multi-backend architecture**: Support for matplotlib (default), seaborn, plotly, and altair
|
|
113
|
+
- **Optional dependencies**: Install only the backends you need
|
|
114
|
+
- **Clean separation**: Core dataeval has zero plotting dependencies
|
|
115
|
+
- **Protocol-based design**: Loose coupling via structural typing (`Plottable` protocol)
|
|
116
|
+
- **Extensible**: Easy to add new backends via `BasePlottingBackend` or custom outputs via `Plottable`
|
|
117
|
+
- **Lazy loading**: Backends are only imported when first used
|
|
118
|
+
- **Type safe**: Static type checking with mypy/pyright via `@runtime_checkable` protocols
|
|
119
|
+
- **DRY architecture**: Centralized routing logic in `BasePlottingBackend`
|
|
120
|
+
|
|
121
|
+
## Architecture
|
|
122
|
+
|
|
123
|
+
The package uses a **protocol-based architecture** for loose coupling between dataeval and dataeval-plots:
|
|
124
|
+
|
|
125
|
+
```
|
|
126
|
+
dataeval/ # Core package
|
|
127
|
+
outputs/
|
|
128
|
+
_bias.py # CoverageOutput, BalanceOutput, DiversityOutput
|
|
129
|
+
_stats.py # BaseStatsOutput
|
|
130
|
+
_workflows.py # SufficiencyOutput
|
|
131
|
+
_drift.py # DriftMVDCOutput
|
|
132
|
+
plotting.py # Convenience hook to dataeval-plots
|
|
133
|
+
|
|
134
|
+
dataeval-plots/ # Separate plotting package
|
|
135
|
+
src/dataeval_plots/
|
|
136
|
+
__init__.py # Main plot() function
|
|
137
|
+
_registry.py # Backend registry with lazy loading
|
|
138
|
+
protocols.py # Protocol definitions (Plottable hierarchy)
|
|
139
|
+
backends/
|
|
140
|
+
_base.py # BasePlottingBackend (abstract routing)
|
|
141
|
+
_matplotlib.py # MatplotlibBackend (default)
|
|
142
|
+
_seaborn.py # SeabornBackend
|
|
143
|
+
_plotly.py # PlotlyBackend
|
|
144
|
+
_altair.py # AltairBackend
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### Protocol-Based Design
|
|
148
|
+
|
|
149
|
+
All DataEval output classes implement the `Plottable` protocol, which requires:
|
|
150
|
+
|
|
151
|
+
- `plot_type()`: Returns a string identifying the plot type (e.g., "coverage", "balance")
|
|
152
|
+
- `meta()`: Returns execution metadata
|
|
153
|
+
|
|
154
|
+
This enables:
|
|
155
|
+
|
|
156
|
+
- **Loose coupling**: dataeval-plots doesn't import concrete classes from dataeval
|
|
157
|
+
- **Type safety**: Static and runtime type checking via `@runtime_checkable` protocols
|
|
158
|
+
- **Extensibility**: Anyone can create custom outputs implementing `Plottable`
|
|
159
|
+
- **Zero dependencies**: Core dataeval has no plotting dependencies
|
|
160
|
+
|
|
161
|
+
## Supported Output Types
|
|
162
|
+
|
|
163
|
+
| Output Type | Plot Type | Description | Source |
|
|
164
|
+
|-------------|-----------|-------------|--------|
|
|
165
|
+
| `CoverageOutput` | "coverage" | Image grid showing uncovered samples | [dataeval/_bias.py](../dataeval/src/dataeval/outputs/_bias.py) |
|
|
166
|
+
| `BalanceOutput` | "balance" | Heatmap of class balance metrics | [dataeval/_bias.py](../dataeval/src/dataeval/outputs/_bias.py) |
|
|
167
|
+
| `DiversityOutput` | "diversity" | Visualization of diversity indices | [dataeval/_bias.py](../dataeval/src/dataeval/outputs/_bias.py) |
|
|
168
|
+
| `SufficiencyOutput` | "sufficiency" | Learning curves with extrapolation | [dataeval/_workflows.py](../dataeval/src/dataeval/outputs/_workflows.py) |
|
|
169
|
+
| `BaseStatsOutput` | "base_stats" | Statistical histograms and distributions | [dataeval/_stats.py](../dataeval/src/dataeval/outputs/_stats.py) |
|
|
170
|
+
| `DriftMVDCOutput` | "drift_mvdc" | Drift detection plots (MVDC analysis) | [dataeval/_drift.py](../dataeval/src/dataeval/outputs/_drift.py) |
|
|
171
|
+
|
|
172
|
+
Each output type implements the `Plottable` protocol and can be plotted using any registered backend.
|
|
173
|
+
|
|
174
|
+
## Extending the Package
|
|
175
|
+
|
|
176
|
+
### Creating Custom Outputs
|
|
177
|
+
|
|
178
|
+
You can create custom output classes that work with the plotting system by implementing the `Plottable` protocol:
|
|
179
|
+
|
|
180
|
+
```python
|
|
181
|
+
from dataclasses import dataclass
|
|
182
|
+
from numpy.typing import NDArray
|
|
183
|
+
from dataeval_plots.protocols import Plottable, ExecutionMetadata
|
|
184
|
+
|
|
185
|
+
@dataclass
|
|
186
|
+
class MyCustomOutput:
|
|
187
|
+
"""Custom output that reuses existing plot type."""
|
|
188
|
+
uncovered_indices: NDArray
|
|
189
|
+
|
|
190
|
+
def plot_type(self) -> str:
|
|
191
|
+
return "coverage" # Reuse existing coverage plotting
|
|
192
|
+
|
|
193
|
+
def meta(self) -> ExecutionMetadata:
|
|
194
|
+
return ExecutionMetadata.empty()
|
|
195
|
+
|
|
196
|
+
# Works seamlessly with existing backends
|
|
197
|
+
result = MyCustomOutput(uncovered_indices=my_data)
|
|
198
|
+
fig = plot(result, images=my_images)
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### Creating Custom Backends
|
|
202
|
+
|
|
203
|
+
Extend `BasePlottingBackend` to create a new plotting backend:
|
|
204
|
+
|
|
205
|
+
```python
|
|
206
|
+
from dataeval_plots.backends._base import BasePlottingBackend
|
|
207
|
+
from dataeval_plots.protocols import PlottableCoverage, PlottableBalance
|
|
208
|
+
from dataeval_plots import register_backend
|
|
209
|
+
|
|
210
|
+
class CustomBackend(BasePlottingBackend):
|
|
211
|
+
"""Custom plotting backend using your preferred library."""
|
|
212
|
+
|
|
213
|
+
def _plot_coverage(self, output: PlottableCoverage, **kwargs):
|
|
214
|
+
# Implement coverage plotting
|
|
215
|
+
# Access output.uncovered_indices, etc.
|
|
216
|
+
return my_figure
|
|
217
|
+
|
|
218
|
+
def _plot_balance(self, output: PlottableBalance, **kwargs):
|
|
219
|
+
# Implement balance plotting
|
|
220
|
+
return my_figure
|
|
221
|
+
|
|
222
|
+
# Implement other _plot_* methods...
|
|
223
|
+
|
|
224
|
+
# Register and use
|
|
225
|
+
register_backend("custom", CustomBackend())
|
|
226
|
+
fig = plot(result, backend="custom")
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
The `BasePlottingBackend` class handles all routing logic automatically - you just implement the plot-type-specific methods (`_plot_coverage`, `_plot_balance`, etc.).
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
# DataEval Plots
|
|
2
|
+
|
|
3
|
+
Multi-backend plotting utilities for DataEval outputs.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# Minimal - no plotting backend included
|
|
9
|
+
pip install dataeval-plots
|
|
10
|
+
|
|
11
|
+
# With matplotlib plotting (recommended)
|
|
12
|
+
pip install dataeval-plots[matplotlib]
|
|
13
|
+
|
|
14
|
+
# With multiple backends
|
|
15
|
+
pip install dataeval-plots[matplotlib,plotly]
|
|
16
|
+
|
|
17
|
+
# Everything
|
|
18
|
+
pip install dataeval-plots[all]
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
For development:
|
|
22
|
+
```bash
|
|
23
|
+
pip install -e dataeval-plots[all]
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Available Backends
|
|
27
|
+
|
|
28
|
+
| Backend | Status | Install With | Description |
|
|
29
|
+
|---------|--------|--------------|-------------|
|
|
30
|
+
| matplotlib | ✅ Default | `[matplotlib]` | Standard publication-quality plots |
|
|
31
|
+
| seaborn | ✅ Available | `[seaborn]` | Statistical data visualization |
|
|
32
|
+
| plotly | ✅ Available | `[plotly]` | Interactive web-based plots |
|
|
33
|
+
| altair | ✅ Available | `[altair]` | Declarative visualization grammar |
|
|
34
|
+
|
|
35
|
+
## Usage
|
|
36
|
+
|
|
37
|
+
### Option 1: Import from dataeval-plots directly
|
|
38
|
+
|
|
39
|
+
```python
|
|
40
|
+
from dataeval_plots import plot
|
|
41
|
+
from dataeval.metrics.bias import coverage
|
|
42
|
+
|
|
43
|
+
result = coverage(embeddings)
|
|
44
|
+
fig = plot(result, images=dataset, top_k=6)
|
|
45
|
+
fig.savefig("coverage.png")
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Option 2: Import from dataeval core (convenience)
|
|
49
|
+
|
|
50
|
+
```python
|
|
51
|
+
from dataeval import plotting
|
|
52
|
+
from dataeval.metrics.bias import coverage
|
|
53
|
+
|
|
54
|
+
result = coverage(embeddings)
|
|
55
|
+
fig = plotting.plot(result, images=dataset)
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Option 3: Set default backend
|
|
59
|
+
|
|
60
|
+
```python
|
|
61
|
+
from dataeval_plots import plot, set_default_backend
|
|
62
|
+
|
|
63
|
+
# Set seaborn as default
|
|
64
|
+
set_default_backend("seaborn")
|
|
65
|
+
fig = plot(result, images=dataset) # Uses seaborn
|
|
66
|
+
|
|
67
|
+
# Override for a specific plot
|
|
68
|
+
fig = plot(result, backend="matplotlib", images=dataset)
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Features
|
|
72
|
+
|
|
73
|
+
- **Multi-backend architecture**: Support for matplotlib (default), seaborn, plotly, and altair
|
|
74
|
+
- **Optional dependencies**: Install only the backends you need
|
|
75
|
+
- **Clean separation**: Core dataeval has zero plotting dependencies
|
|
76
|
+
- **Protocol-based design**: Loose coupling via structural typing (`Plottable` protocol)
|
|
77
|
+
- **Extensible**: Easy to add new backends via `BasePlottingBackend` or custom outputs via `Plottable`
|
|
78
|
+
- **Lazy loading**: Backends are only imported when first used
|
|
79
|
+
- **Type safe**: Static type checking with mypy/pyright via `@runtime_checkable` protocols
|
|
80
|
+
- **DRY architecture**: Centralized routing logic in `BasePlottingBackend`
|
|
81
|
+
|
|
82
|
+
## Architecture
|
|
83
|
+
|
|
84
|
+
The package uses a **protocol-based architecture** for loose coupling between dataeval and dataeval-plots:
|
|
85
|
+
|
|
86
|
+
```
|
|
87
|
+
dataeval/ # Core package
|
|
88
|
+
outputs/
|
|
89
|
+
_bias.py # CoverageOutput, BalanceOutput, DiversityOutput
|
|
90
|
+
_stats.py # BaseStatsOutput
|
|
91
|
+
_workflows.py # SufficiencyOutput
|
|
92
|
+
_drift.py # DriftMVDCOutput
|
|
93
|
+
plotting.py # Convenience hook to dataeval-plots
|
|
94
|
+
|
|
95
|
+
dataeval-plots/ # Separate plotting package
|
|
96
|
+
src/dataeval_plots/
|
|
97
|
+
__init__.py # Main plot() function
|
|
98
|
+
_registry.py # Backend registry with lazy loading
|
|
99
|
+
protocols.py # Protocol definitions (Plottable hierarchy)
|
|
100
|
+
backends/
|
|
101
|
+
_base.py # BasePlottingBackend (abstract routing)
|
|
102
|
+
_matplotlib.py # MatplotlibBackend (default)
|
|
103
|
+
_seaborn.py # SeabornBackend
|
|
104
|
+
_plotly.py # PlotlyBackend
|
|
105
|
+
_altair.py # AltairBackend
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Protocol-Based Design
|
|
109
|
+
|
|
110
|
+
All DataEval output classes implement the `Plottable` protocol, which requires:
|
|
111
|
+
|
|
112
|
+
- `plot_type()`: Returns a string identifying the plot type (e.g., "coverage", "balance")
|
|
113
|
+
- `meta()`: Returns execution metadata
|
|
114
|
+
|
|
115
|
+
This enables:
|
|
116
|
+
|
|
117
|
+
- **Loose coupling**: dataeval-plots doesn't import concrete classes from dataeval
|
|
118
|
+
- **Type safety**: Static and runtime type checking via `@runtime_checkable` protocols
|
|
119
|
+
- **Extensibility**: Anyone can create custom outputs implementing `Plottable`
|
|
120
|
+
- **Zero dependencies**: Core dataeval has no plotting dependencies
|
|
121
|
+
|
|
122
|
+
## Supported Output Types
|
|
123
|
+
|
|
124
|
+
| Output Type | Plot Type | Description | Source |
|
|
125
|
+
|-------------|-----------|-------------|--------|
|
|
126
|
+
| `CoverageOutput` | "coverage" | Image grid showing uncovered samples | [dataeval/_bias.py](../dataeval/src/dataeval/outputs/_bias.py) |
|
|
127
|
+
| `BalanceOutput` | "balance" | Heatmap of class balance metrics | [dataeval/_bias.py](../dataeval/src/dataeval/outputs/_bias.py) |
|
|
128
|
+
| `DiversityOutput` | "diversity" | Visualization of diversity indices | [dataeval/_bias.py](../dataeval/src/dataeval/outputs/_bias.py) |
|
|
129
|
+
| `SufficiencyOutput` | "sufficiency" | Learning curves with extrapolation | [dataeval/_workflows.py](../dataeval/src/dataeval/outputs/_workflows.py) |
|
|
130
|
+
| `BaseStatsOutput` | "base_stats" | Statistical histograms and distributions | [dataeval/_stats.py](../dataeval/src/dataeval/outputs/_stats.py) |
|
|
131
|
+
| `DriftMVDCOutput` | "drift_mvdc" | Drift detection plots (MVDC analysis) | [dataeval/_drift.py](../dataeval/src/dataeval/outputs/_drift.py) |
|
|
132
|
+
|
|
133
|
+
Each output type implements the `Plottable` protocol and can be plotted using any registered backend.
|
|
134
|
+
|
|
135
|
+
## Extending the Package
|
|
136
|
+
|
|
137
|
+
### Creating Custom Outputs
|
|
138
|
+
|
|
139
|
+
You can create custom output classes that work with the plotting system by implementing the `Plottable` protocol:
|
|
140
|
+
|
|
141
|
+
```python
|
|
142
|
+
from dataclasses import dataclass
|
|
143
|
+
from numpy.typing import NDArray
|
|
144
|
+
from dataeval_plots.protocols import Plottable, ExecutionMetadata
|
|
145
|
+
|
|
146
|
+
@dataclass
|
|
147
|
+
class MyCustomOutput:
|
|
148
|
+
"""Custom output that reuses existing plot type."""
|
|
149
|
+
uncovered_indices: NDArray
|
|
150
|
+
|
|
151
|
+
def plot_type(self) -> str:
|
|
152
|
+
return "coverage" # Reuse existing coverage plotting
|
|
153
|
+
|
|
154
|
+
def meta(self) -> ExecutionMetadata:
|
|
155
|
+
return ExecutionMetadata.empty()
|
|
156
|
+
|
|
157
|
+
# Works seamlessly with existing backends
|
|
158
|
+
result = MyCustomOutput(uncovered_indices=my_data)
|
|
159
|
+
fig = plot(result, images=my_images)
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### Creating Custom Backends
|
|
163
|
+
|
|
164
|
+
Extend `BasePlottingBackend` to create a new plotting backend:
|
|
165
|
+
|
|
166
|
+
```python
|
|
167
|
+
from dataeval_plots.backends._base import BasePlottingBackend
|
|
168
|
+
from dataeval_plots.protocols import PlottableCoverage, PlottableBalance
|
|
169
|
+
from dataeval_plots import register_backend
|
|
170
|
+
|
|
171
|
+
class CustomBackend(BasePlottingBackend):
|
|
172
|
+
"""Custom plotting backend using your preferred library."""
|
|
173
|
+
|
|
174
|
+
def _plot_coverage(self, output: PlottableCoverage, **kwargs):
|
|
175
|
+
# Implement coverage plotting
|
|
176
|
+
# Access output.uncovered_indices, etc.
|
|
177
|
+
return my_figure
|
|
178
|
+
|
|
179
|
+
def _plot_balance(self, output: PlottableBalance, **kwargs):
|
|
180
|
+
# Implement balance plotting
|
|
181
|
+
return my_figure
|
|
182
|
+
|
|
183
|
+
# Implement other _plot_* methods...
|
|
184
|
+
|
|
185
|
+
# Register and use
|
|
186
|
+
register_backend("custom", CustomBackend())
|
|
187
|
+
fig = plot(result, backend="custom")
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
The `BasePlottingBackend` class handles all routing logic automatically - you just implement the plot-type-specific methods (`_plot_coverage`, `_plot_balance`, etc.).
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "dataeval-plots"
|
|
3
|
+
dynamic = ["version"]
|
|
4
|
+
description = "DataEval companion package for plotting utilities"
|
|
5
|
+
authors = [
|
|
6
|
+
{ name = "Andrew Weng", email = "andrew.weng@ariacoustics.com" },
|
|
7
|
+
{ name = "Ryan Wood", email = "ryan.wood@ariacoustics.com" },
|
|
8
|
+
{ name = "Shaun Jullens", email = "shaun.jullens@ariacoustics.com" },
|
|
9
|
+
]
|
|
10
|
+
requires-python = ">=3.10,<3.14"
|
|
11
|
+
readme = "README.md"
|
|
12
|
+
license = "MIT"
|
|
13
|
+
maintainers = [
|
|
14
|
+
{ name = "ARiA", email = "dataeval@ariacoustics.com" },
|
|
15
|
+
]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Development Status :: 4 - Beta",
|
|
18
|
+
"Operating System :: OS Independent",
|
|
19
|
+
"Intended Audience :: Science/Research",
|
|
20
|
+
"License :: OSI Approved :: MIT License",
|
|
21
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
22
|
+
"Programming Language :: Python :: 3.10",
|
|
23
|
+
"Programming Language :: Python :: 3.11",
|
|
24
|
+
"Programming Language :: Python :: 3.12",
|
|
25
|
+
"Programming Language :: Python :: 3.13",
|
|
26
|
+
"Topic :: Scientific/Engineering",
|
|
27
|
+
]
|
|
28
|
+
dependencies = [
|
|
29
|
+
"numpy>=1.24.2,<2.3; python_version<'3.12'",
|
|
30
|
+
"numpy>=1.26.2,<2.3; python_version>='3.12'",
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
[project.optional-dependencies]
|
|
34
|
+
matplotlib = ["matplotlib>=3.7.1"]
|
|
35
|
+
seaborn = ["matplotlib>=3.7.1", "seaborn>=0.12"]
|
|
36
|
+
plotly = ["plotly>=5.0"]
|
|
37
|
+
altair = ["altair>=5.0"]
|
|
38
|
+
all = [
|
|
39
|
+
"matplotlib>=3.7.1",
|
|
40
|
+
"seaborn>=0.12",
|
|
41
|
+
"plotly>=5.0",
|
|
42
|
+
"altair>=5.0",
|
|
43
|
+
]
|
|
44
|
+
|
|
45
|
+
[dependency-groups]
|
|
46
|
+
base = [
|
|
47
|
+
"nox>=2025.5.1",
|
|
48
|
+
"nox-uv>=0.6.2",
|
|
49
|
+
"uv>=0.8.0",
|
|
50
|
+
]
|
|
51
|
+
lint = [
|
|
52
|
+
{ include-group = "base" },
|
|
53
|
+
"ruff>=0.11",
|
|
54
|
+
"codespell[toml]>=2.3",
|
|
55
|
+
]
|
|
56
|
+
test = [
|
|
57
|
+
{ include-group = "base" },
|
|
58
|
+
"pytest>=8.3",
|
|
59
|
+
"pytest-cov>=6.1",
|
|
60
|
+
"coverage[toml]>=7.6",
|
|
61
|
+
]
|
|
62
|
+
type = [
|
|
63
|
+
{ include-group = "base" },
|
|
64
|
+
"pyright[nodejs]>=1.1.400",
|
|
65
|
+
]
|
|
66
|
+
dev = [
|
|
67
|
+
{ include-group = "base" },
|
|
68
|
+
{ include-group = "lint" },
|
|
69
|
+
{ include-group = "test" },
|
|
70
|
+
{ include-group = "type" },
|
|
71
|
+
]
|
|
72
|
+
|
|
73
|
+
[project.urls]
|
|
74
|
+
Homepage = "https://dataeval.ai/"
|
|
75
|
+
Repository = "https://github.com/aria-ml/dataeval/"
|
|
76
|
+
Documentation = "https://dataeval.readthedocs.io/"
|
|
77
|
+
|
|
78
|
+
[tool.hatch.build.targets.sdist]
|
|
79
|
+
include = ["src/dataeval_plots"]
|
|
80
|
+
|
|
81
|
+
[tool.hatch.build.targets.wheel]
|
|
82
|
+
packages = ["src/dataeval_plots"]
|
|
83
|
+
|
|
84
|
+
[tool.hatch.build.targets.wheel.sources]
|
|
85
|
+
"src/dataeval_plots" = "dataeval_plots"
|
|
86
|
+
|
|
87
|
+
[tool.hatch.version]
|
|
88
|
+
source = "vcs"
|
|
89
|
+
|
|
90
|
+
[tool.hatch.build.hooks.vcs]
|
|
91
|
+
version-file = "src/dataeval_plots/_version.py"
|
|
92
|
+
|
|
93
|
+
[tool.pytest.ini_options]
|
|
94
|
+
testpaths = ["tests"]
|
|
95
|
+
addopts = [
|
|
96
|
+
"--pythonwarnings=ignore::DeprecationWarning",
|
|
97
|
+
"--verbose",
|
|
98
|
+
]
|
|
99
|
+
|
|
100
|
+
[tool.coverage.run]
|
|
101
|
+
source = ["src/dataeval_plots"]
|
|
102
|
+
branch = true
|
|
103
|
+
|
|
104
|
+
[tool.coverage.report]
|
|
105
|
+
exclude_also = [
|
|
106
|
+
"raise NotImplementedError",
|
|
107
|
+
": \\.\\.\\.",
|
|
108
|
+
"_version.py",
|
|
109
|
+
]
|
|
110
|
+
include = ["*/src/dataeval_plots/*"]
|
|
111
|
+
fail_under = 70
|
|
112
|
+
|
|
113
|
+
[tool.codespell]
|
|
114
|
+
skip = './*env*,./output,uv.lock'
|
|
115
|
+
|
|
116
|
+
[tool.ruff]
|
|
117
|
+
exclude = [
|
|
118
|
+
".github",
|
|
119
|
+
".vscode",
|
|
120
|
+
"*env*",
|
|
121
|
+
".nox",
|
|
122
|
+
]
|
|
123
|
+
line-length = 120
|
|
124
|
+
indent-width = 4
|
|
125
|
+
target-version = "py310"
|
|
126
|
+
|
|
127
|
+
[tool.ruff.lint]
|
|
128
|
+
select = ["A", "ANN", "C4", "C90", "E", "F", "I", "NPY", "S", "SIM", "RET", "RUF100", "UP"]
|
|
129
|
+
ignore = ["ANN401", "C901", "NPY002"]
|
|
130
|
+
fixable = ["ALL"]
|
|
131
|
+
unfixable = []
|
|
132
|
+
dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"
|
|
133
|
+
per-file-ignores = { "!src/*" = ["ANN", "S", "RET"]}
|
|
134
|
+
|
|
135
|
+
[tool.ruff.lint.isort]
|
|
136
|
+
known-first-party = ["dataeval_plots"]
|
|
137
|
+
|
|
138
|
+
[tool.ruff.format]
|
|
139
|
+
quote-style = "double"
|
|
140
|
+
indent-style = "space"
|
|
141
|
+
skip-magic-trailing-comma = false
|
|
142
|
+
line-ending = "auto"
|
|
143
|
+
|
|
144
|
+
[build-system]
|
|
145
|
+
requires = ["hatchling", "hatch-vcs"]
|
|
146
|
+
build-backend = "hatchling.build"
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"""Plotting backends for DataEval outputs."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
from dataeval_plots._registry import get_backend, register_backend, set_default_backend
|
|
8
|
+
from dataeval_plots.protocols import Plottable
|
|
9
|
+
|
|
10
|
+
__all__ = ["plot", "register_backend", "set_default_backend", "get_backend"]
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def plot(output: Plottable, /, backend: str | None = None, **kwargs: Any) -> Any:
|
|
14
|
+
"""
|
|
15
|
+
Plot any DataEval output object.
|
|
16
|
+
|
|
17
|
+
Parameters
|
|
18
|
+
----------
|
|
19
|
+
output : Plottable
|
|
20
|
+
DataEval output object to visualize (must implement Plottable protocol)
|
|
21
|
+
backend : str or None, default None
|
|
22
|
+
Plotting backend ('matplotlib', 'seaborn', 'plotly', 'altair').
|
|
23
|
+
If None, uses default backend.
|
|
24
|
+
**kwargs
|
|
25
|
+
Backend-specific plotting parameters
|
|
26
|
+
|
|
27
|
+
Returns
|
|
28
|
+
-------
|
|
29
|
+
Figure
|
|
30
|
+
Backend-specific figure object
|
|
31
|
+
|
|
32
|
+
Raises
|
|
33
|
+
------
|
|
34
|
+
ImportError
|
|
35
|
+
If backend dependencies are not installed
|
|
36
|
+
NotImplementedError
|
|
37
|
+
If plotting is not implemented for the given output type
|
|
38
|
+
|
|
39
|
+
Examples
|
|
40
|
+
--------
|
|
41
|
+
>>> from dataeval_plots import plot
|
|
42
|
+
>>> from dataeval.metrics.bias import coverage
|
|
43
|
+
>>> result = coverage(embeddings)
|
|
44
|
+
>>> fig = plot(result, images=dataset, top_k=6)
|
|
45
|
+
>>> fig.savefig("coverage.png")
|
|
46
|
+
|
|
47
|
+
>>> # Use a different backend
|
|
48
|
+
>>> plot(result, backend="seaborn", images=dataset)
|
|
49
|
+
|
|
50
|
+
>>> # Set default backend
|
|
51
|
+
>>> from dataeval_plots import set_default_backend
|
|
52
|
+
>>> set_default_backend("seaborn")
|
|
53
|
+
>>> plot(result, images=dataset) # Uses seaborn
|
|
54
|
+
"""
|
|
55
|
+
plotting_backend = get_backend(backend)
|
|
56
|
+
return plotting_backend.plot(output, **kwargs)
|