maidr 0.23.1__tar.gz → 0.25.0__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.
- {maidr-0.23.1 → maidr-0.25.0}/PKG-INFO +1 -1
- {maidr-0.23.1 → maidr-0.25.0}/maidr/__init__.py +1 -1
- {maidr-0.23.1 → maidr-0.25.0}/maidr/core/enum/maidr_key.py +2 -0
- {maidr-0.23.1 → maidr-0.25.0}/maidr/core/maidr.py +7 -4
- {maidr-0.23.1 → maidr-0.25.0}/maidr/core/plot/boxplot.py +108 -2
- {maidr-0.23.1 → maidr-0.25.0}/maidr/core/plot/lineplot.py +2 -1
- {maidr-0.23.1 → maidr-0.25.0}/maidr/patch/highlight.py +4 -3
- {maidr-0.23.1 → maidr-0.25.0}/pyproject.toml +1 -1
- {maidr-0.23.1 → maidr-0.25.0}/LICENSE +0 -0
- {maidr-0.23.1 → maidr-0.25.0}/README.md +0 -0
- {maidr-0.23.1 → maidr-0.25.0}/maidr/api.py +0 -0
- {maidr-0.23.1 → maidr-0.25.0}/maidr/core/__init__.py +0 -0
- {maidr-0.23.1 → maidr-0.25.0}/maidr/core/context_manager.py +0 -0
- {maidr-0.23.1 → maidr-0.25.0}/maidr/core/enum/__init__.py +0 -0
- {maidr-0.23.1 → maidr-0.25.0}/maidr/core/enum/library.py +0 -0
- {maidr-0.23.1 → maidr-0.25.0}/maidr/core/enum/plot_type.py +0 -0
- {maidr-0.23.1 → maidr-0.25.0}/maidr/core/figure_manager.py +0 -0
- {maidr-0.23.1 → maidr-0.25.0}/maidr/core/plot/__init__.py +0 -0
- {maidr-0.23.1 → maidr-0.25.0}/maidr/core/plot/barplot.py +0 -0
- {maidr-0.23.1 → maidr-0.25.0}/maidr/core/plot/grouped_barplot.py +0 -0
- {maidr-0.23.1 → maidr-0.25.0}/maidr/core/plot/heatmap.py +0 -0
- {maidr-0.23.1 → maidr-0.25.0}/maidr/core/plot/histogram.py +0 -0
- {maidr-0.23.1 → maidr-0.25.0}/maidr/core/plot/maidr_plot.py +0 -0
- {maidr-0.23.1 → maidr-0.25.0}/maidr/core/plot/maidr_plot_factory.py +0 -0
- {maidr-0.23.1 → maidr-0.25.0}/maidr/core/plot/scatterplot.py +0 -0
- {maidr-0.23.1 → maidr-0.25.0}/maidr/exception/__init__.py +0 -0
- {maidr-0.23.1 → maidr-0.25.0}/maidr/exception/extraction_error.py +0 -0
- {maidr-0.23.1 → maidr-0.25.0}/maidr/patch/__init__.py +0 -0
- {maidr-0.23.1 → maidr-0.25.0}/maidr/patch/barplot.py +0 -0
- {maidr-0.23.1 → maidr-0.25.0}/maidr/patch/boxplot.py +0 -0
- {maidr-0.23.1 → maidr-0.25.0}/maidr/patch/clear.py +0 -0
- {maidr-0.23.1 → maidr-0.25.0}/maidr/patch/common.py +0 -0
- {maidr-0.23.1 → maidr-0.25.0}/maidr/patch/heatmap.py +0 -0
- {maidr-0.23.1 → maidr-0.25.0}/maidr/patch/histogram.py +0 -0
- {maidr-0.23.1 → maidr-0.25.0}/maidr/patch/lineplot.py +0 -0
- {maidr-0.23.1 → maidr-0.25.0}/maidr/patch/scatterplot.py +0 -0
- {maidr-0.23.1 → maidr-0.25.0}/maidr/util/__init__.py +0 -0
- {maidr-0.23.1 → maidr-0.25.0}/maidr/util/environment.py +0 -0
- {maidr-0.23.1 → maidr-0.25.0}/maidr/util/mixin/__init__.py +0 -0
- {maidr-0.23.1 → maidr-0.25.0}/maidr/util/mixin/extractor_mixin.py +0 -0
- {maidr-0.23.1 → maidr-0.25.0}/maidr/util/mixin/merger_mixin.py +0 -0
- {maidr-0.23.1 → maidr-0.25.0}/maidr/widget/__init__.py +0 -0
- {maidr-0.23.1 → maidr-0.25.0}/maidr/widget/shiny.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: maidr
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.25.0
|
|
4
4
|
Summary: Multimodal Access and Interactive Data Representations
|
|
5
5
|
License: GPL-3.0-or-later
|
|
6
6
|
Keywords: accessibility,visualization,sonification,braille,tactile,multimodal,data representation,blind,low vision,visual impairments
|
|
@@ -122,7 +122,10 @@ class Maidr:
|
|
|
122
122
|
|
|
123
123
|
def _create_html_tag(self) -> Tag:
|
|
124
124
|
"""Create the MAIDR HTML using HTML tags."""
|
|
125
|
-
tagged_elements = [
|
|
125
|
+
tagged_elements: list[Any] = [
|
|
126
|
+
element for plot in self._plots for element in plot.elements
|
|
127
|
+
]
|
|
128
|
+
|
|
126
129
|
selector_ids = []
|
|
127
130
|
for i, plot in enumerate(self._plots):
|
|
128
131
|
for _ in plot.elements:
|
|
@@ -149,7 +152,7 @@ class Maidr:
|
|
|
149
152
|
for i, plot in enumerate(self._plots):
|
|
150
153
|
schema = plot.schema
|
|
151
154
|
|
|
152
|
-
if MaidrKey.SELECTOR in schema:
|
|
155
|
+
if MaidrKey.SELECTOR in schema and plot.type != PlotType.BOX:
|
|
153
156
|
if isinstance(schema[MaidrKey.SELECTOR], str):
|
|
154
157
|
schema[MaidrKey.SELECTOR] = schema[MaidrKey.SELECTOR].replace(
|
|
155
158
|
"maidr='true'", f"maidr='{self.selector_ids[i]}'"
|
|
@@ -238,7 +241,7 @@ class Maidr:
|
|
|
238
241
|
def _inject_plot(plot: HTML, maidr: str, maidr_id) -> Tag:
|
|
239
242
|
"""Embed the plot and associated MAIDR scripts into the HTML structure."""
|
|
240
243
|
# MAIDR_TS_CDN_URL = "http://localhost:8080/maidr.js" # DEMO URL
|
|
241
|
-
MAIDR_TS_CDN_URL = "https://cdn.jsdelivr.net/npm/maidr
|
|
244
|
+
MAIDR_TS_CDN_URL = "https://cdn.jsdelivr.net/npm/maidr/dist/maidr.js"
|
|
242
245
|
|
|
243
246
|
script = f"""
|
|
244
247
|
if (!document.querySelector('script[src="{MAIDR_TS_CDN_URL}"]'))
|
|
@@ -260,7 +263,7 @@ class Maidr:
|
|
|
260
263
|
base_html = tags.div(
|
|
261
264
|
tags.link(
|
|
262
265
|
rel="stylesheet",
|
|
263
|
-
href="https://cdn.jsdelivr.net/npm/maidr/dist/maidr_style.
|
|
266
|
+
href="https://cdn.jsdelivr.net/npm/maidr/dist/maidr_style.css",
|
|
264
267
|
),
|
|
265
268
|
tags.script(script, type="text/javascript"),
|
|
266
269
|
tags.div(plot),
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import uuid
|
|
4
|
+
|
|
3
5
|
from matplotlib.axes import Axes
|
|
4
6
|
|
|
5
7
|
from maidr.core.enum import MaidrKey, PlotType
|
|
@@ -119,6 +121,40 @@ class BoxPlotExtractor:
|
|
|
119
121
|
return data
|
|
120
122
|
|
|
121
123
|
|
|
124
|
+
class BoxPlotElementsExtractor:
|
|
125
|
+
def __init__(self, orientation: str = "vert"):
|
|
126
|
+
self.orientation = orientation
|
|
127
|
+
|
|
128
|
+
def extract_whiskers(self, whiskers: list) -> list[dict]:
|
|
129
|
+
return self._extract_extremes(whiskers, MaidrKey.Q1, MaidrKey.Q3)
|
|
130
|
+
|
|
131
|
+
def extract_caps(self, caps: list) -> list[dict]:
|
|
132
|
+
return self._extract_extremes(caps, MaidrKey.MIN, MaidrKey.MAX)
|
|
133
|
+
|
|
134
|
+
def _extract_extremes(
|
|
135
|
+
self, extremes: list, start_key: MaidrKey, end_key: MaidrKey
|
|
136
|
+
) -> list[dict]:
|
|
137
|
+
elements = []
|
|
138
|
+
|
|
139
|
+
for start, end in zip(extremes[::2], extremes[1::2]):
|
|
140
|
+
elements.append(
|
|
141
|
+
{
|
|
142
|
+
start_key.value: start,
|
|
143
|
+
end_key.value: end,
|
|
144
|
+
}
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
return elements
|
|
148
|
+
|
|
149
|
+
def extract_outliers(self, fliers: list, caps: list):
|
|
150
|
+
elements = []
|
|
151
|
+
|
|
152
|
+
for outlier, _ in zip(fliers, caps):
|
|
153
|
+
elements.append(outlier)
|
|
154
|
+
|
|
155
|
+
return elements
|
|
156
|
+
|
|
157
|
+
|
|
122
158
|
class BoxPlot(
|
|
123
159
|
MaidrPlot,
|
|
124
160
|
ContainerExtractorMixin,
|
|
@@ -131,7 +167,33 @@ class BoxPlot(
|
|
|
131
167
|
self._bxp_stats = kwargs.pop("bxp_stats", None)
|
|
132
168
|
self._orientation = kwargs.pop("orientation", "vert")
|
|
133
169
|
self._bxp_extractor = BoxPlotExtractor(orientation=self._orientation)
|
|
134
|
-
self.
|
|
170
|
+
self._bxp_elements_extractor = BoxPlotElementsExtractor(
|
|
171
|
+
orientation=self._orientation
|
|
172
|
+
)
|
|
173
|
+
self._support_highlighting = True
|
|
174
|
+
self.elements_map = {
|
|
175
|
+
"min": [],
|
|
176
|
+
"max": [],
|
|
177
|
+
"median": [],
|
|
178
|
+
"boxes": [],
|
|
179
|
+
"outliers": [],
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
def _get_selector(self) -> list[dict]:
|
|
183
|
+
mins, maxs, medians, boxes, outliers = self.elements_map.values()
|
|
184
|
+
selector = []
|
|
185
|
+
for min, max, median, box, outlier in zip(mins, maxs, medians, boxes, outliers):
|
|
186
|
+
selector.append(
|
|
187
|
+
{
|
|
188
|
+
MaidrKey.LOWER_OUTLIER.value: ["g[id=" + outlier + "] > g > use"],
|
|
189
|
+
MaidrKey.MIN.value: "g[id=" + min + "] > path",
|
|
190
|
+
MaidrKey.MAX.value: "g[id=" + max + "] > path",
|
|
191
|
+
MaidrKey.Q2.value: "g[id=" + median + "] > path",
|
|
192
|
+
MaidrKey.IQ.value: "g[id=" + box + "] > path",
|
|
193
|
+
MaidrKey.UPPER_OUTLIER.value: ["g[id=" + outlier + "] > g > use"],
|
|
194
|
+
}
|
|
195
|
+
)
|
|
196
|
+
return selector if self._orientation == "vert" else list(reversed(selector))
|
|
135
197
|
|
|
136
198
|
def render(self) -> dict:
|
|
137
199
|
base_schema = super().render()
|
|
@@ -150,11 +212,14 @@ class BoxPlot(
|
|
|
150
212
|
if bxp_stats is None:
|
|
151
213
|
return None
|
|
152
214
|
|
|
153
|
-
bxp_maidr = []
|
|
154
215
|
whiskers = self._bxp_extractor.extract_whiskers(bxp_stats["whiskers"])
|
|
155
216
|
caps = self._bxp_extractor.extract_caps(bxp_stats["caps"])
|
|
156
217
|
medians = self._bxp_extractor.extract_medians(bxp_stats["medians"])
|
|
157
218
|
outliers = self._bxp_extractor.extract_outliers(bxp_stats["fliers"], caps)
|
|
219
|
+
|
|
220
|
+
caps_elements = self._bxp_elements_extractor.extract_caps(bxp_stats["caps"])
|
|
221
|
+
bxp_maidr = []
|
|
222
|
+
|
|
158
223
|
levels = (
|
|
159
224
|
self.extract_level(self.ax, MaidrKey.X)
|
|
160
225
|
if self._orientation == "vert"
|
|
@@ -163,6 +228,47 @@ class BoxPlot(
|
|
|
163
228
|
if levels is None:
|
|
164
229
|
levels = []
|
|
165
230
|
|
|
231
|
+
_pairs = [(e["min"], e["max"]) for e in caps_elements if e]
|
|
232
|
+
|
|
233
|
+
if _pairs:
|
|
234
|
+
mins, maxs = map(list, zip(*_pairs))
|
|
235
|
+
else:
|
|
236
|
+
mins, maxs = [], []
|
|
237
|
+
|
|
238
|
+
elements = []
|
|
239
|
+
|
|
240
|
+
for element in mins:
|
|
241
|
+
gid = "maidr-" + str(uuid.uuid4())
|
|
242
|
+
element.set_gid(gid)
|
|
243
|
+
self.elements_map["min"].append(gid)
|
|
244
|
+
elements.append(element)
|
|
245
|
+
|
|
246
|
+
for element in maxs:
|
|
247
|
+
gid = "maidr-" + str(uuid.uuid4())
|
|
248
|
+
element.set_gid(gid)
|
|
249
|
+
self.elements_map["max"].append(gid)
|
|
250
|
+
elements.append(element)
|
|
251
|
+
|
|
252
|
+
for element in bxp_stats["medians"]:
|
|
253
|
+
gid = "maidr-" + str(uuid.uuid4())
|
|
254
|
+
element.set_gid(gid)
|
|
255
|
+
self.elements_map["median"].append(gid)
|
|
256
|
+
elements.append(element)
|
|
257
|
+
|
|
258
|
+
for element in bxp_stats["boxes"]:
|
|
259
|
+
gid = "maidr-" + str(uuid.uuid4())
|
|
260
|
+
element.set_gid(gid)
|
|
261
|
+
self.elements_map["boxes"].append(gid)
|
|
262
|
+
elements.append(element)
|
|
263
|
+
|
|
264
|
+
for element in bxp_stats["fliers"]:
|
|
265
|
+
gid = "maidr-" + str(uuid.uuid4())
|
|
266
|
+
element.set_gid(gid)
|
|
267
|
+
self.elements_map["outliers"].append(gid)
|
|
268
|
+
elements.append(element)
|
|
269
|
+
|
|
270
|
+
self._elements.extend(elements)
|
|
271
|
+
|
|
166
272
|
for whisker, cap, median, outlier, level in zip(
|
|
167
273
|
whiskers, caps, medians, outliers, levels
|
|
168
274
|
):
|
|
@@ -90,7 +90,8 @@ class MultiLinePlot(MaidrPlot, LineExtractorMixin):
|
|
|
90
90
|
{
|
|
91
91
|
MaidrKey.X: float(x),
|
|
92
92
|
MaidrKey.Y: float(y),
|
|
93
|
-
# Replace labels starting with '_child'
|
|
93
|
+
# Replace labels starting with '_child'
|
|
94
|
+
# with an empty string to exclude
|
|
94
95
|
# internal or non-relevant labels from being used as identifiers.
|
|
95
96
|
MaidrKey.FILL: (label if not label.startswith("_child") else ""),
|
|
96
97
|
}
|
|
@@ -5,7 +5,6 @@ import uuid
|
|
|
5
5
|
import wrapt
|
|
6
6
|
from matplotlib.backends.backend_svg import XMLWriter
|
|
7
7
|
from matplotlib.collections import PathCollection, QuadMesh
|
|
8
|
-
from matplotlib.figure import Figure
|
|
9
8
|
from matplotlib.lines import Line2D
|
|
10
9
|
from matplotlib.patches import Patch
|
|
11
10
|
|
|
@@ -20,8 +19,10 @@ def inject_maidr_attribute(wrapped, instance, args, kwargs):
|
|
|
20
19
|
|
|
21
20
|
|
|
22
21
|
def tag_elements(wrapped, instance, args, kwargs):
|
|
23
|
-
id = str(
|
|
24
|
-
|
|
22
|
+
id = str(instance.get_gid())
|
|
23
|
+
if not id.startswith("maidr-"):
|
|
24
|
+
id = "maidr-" + str(uuid.uuid4())
|
|
25
|
+
instance.set_gid(id)
|
|
25
26
|
with HighlightContextManager.set_maidr_element(instance, id):
|
|
26
27
|
return wrapped(*args, **kwargs)
|
|
27
28
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|