maidr 0.14.0__tar.gz → 0.16.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.
Files changed (45) hide show
  1. {maidr-0.14.0 → maidr-0.16.0}/PKG-INFO +1 -1
  2. {maidr-0.14.0 → maidr-0.16.0}/maidr/__init__.py +1 -1
  3. {maidr-0.14.0 → maidr-0.16.0}/maidr/core/figure_manager.py +5 -5
  4. {maidr-0.14.0 → maidr-0.16.0}/maidr/core/maidr.py +5 -1
  5. {maidr-0.14.0 → maidr-0.16.0}/maidr/core/plot/grouped_barplot.py +1 -1
  6. maidr-0.16.0/maidr/core/plot/lineplot.py +102 -0
  7. {maidr-0.14.0 → maidr-0.16.0}/maidr/core/plot/maidr_plot_factory.py +2 -2
  8. maidr-0.16.0/maidr/patch/lineplot.py +38 -0
  9. {maidr-0.14.0 → maidr-0.16.0}/maidr/util/mixin/extractor_mixin.py +11 -0
  10. {maidr-0.14.0 → maidr-0.16.0}/pyproject.toml +1 -1
  11. maidr-0.14.0/maidr/core/plot/lineplot.py +0 -45
  12. maidr-0.14.0/maidr/patch/lineplot.py +0 -20
  13. {maidr-0.14.0 → maidr-0.16.0}/LICENSE +0 -0
  14. {maidr-0.14.0 → maidr-0.16.0}/README.md +0 -0
  15. {maidr-0.14.0 → maidr-0.16.0}/maidr/api.py +0 -0
  16. {maidr-0.14.0 → maidr-0.16.0}/maidr/core/__init__.py +0 -0
  17. {maidr-0.14.0 → maidr-0.16.0}/maidr/core/context_manager.py +0 -0
  18. {maidr-0.14.0 → maidr-0.16.0}/maidr/core/enum/__init__.py +0 -0
  19. {maidr-0.14.0 → maidr-0.16.0}/maidr/core/enum/library.py +0 -0
  20. {maidr-0.14.0 → maidr-0.16.0}/maidr/core/enum/maidr_key.py +0 -0
  21. {maidr-0.14.0 → maidr-0.16.0}/maidr/core/enum/plot_type.py +0 -0
  22. {maidr-0.14.0 → maidr-0.16.0}/maidr/core/plot/__init__.py +0 -0
  23. {maidr-0.14.0 → maidr-0.16.0}/maidr/core/plot/barplot.py +0 -0
  24. {maidr-0.14.0 → maidr-0.16.0}/maidr/core/plot/boxplot.py +0 -0
  25. {maidr-0.14.0 → maidr-0.16.0}/maidr/core/plot/heatmap.py +0 -0
  26. {maidr-0.14.0 → maidr-0.16.0}/maidr/core/plot/histogram.py +0 -0
  27. {maidr-0.14.0 → maidr-0.16.0}/maidr/core/plot/maidr_plot.py +0 -0
  28. {maidr-0.14.0 → maidr-0.16.0}/maidr/core/plot/scatterplot.py +0 -0
  29. {maidr-0.14.0 → maidr-0.16.0}/maidr/exception/__init__.py +0 -0
  30. {maidr-0.14.0 → maidr-0.16.0}/maidr/exception/extraction_error.py +0 -0
  31. {maidr-0.14.0 → maidr-0.16.0}/maidr/patch/__init__.py +0 -0
  32. {maidr-0.14.0 → maidr-0.16.0}/maidr/patch/barplot.py +0 -0
  33. {maidr-0.14.0 → maidr-0.16.0}/maidr/patch/boxplot.py +0 -0
  34. {maidr-0.14.0 → maidr-0.16.0}/maidr/patch/clear.py +0 -0
  35. {maidr-0.14.0 → maidr-0.16.0}/maidr/patch/common.py +0 -0
  36. {maidr-0.14.0 → maidr-0.16.0}/maidr/patch/heatmap.py +0 -0
  37. {maidr-0.14.0 → maidr-0.16.0}/maidr/patch/highlight.py +0 -0
  38. {maidr-0.14.0 → maidr-0.16.0}/maidr/patch/histogram.py +0 -0
  39. {maidr-0.14.0 → maidr-0.16.0}/maidr/patch/scatterplot.py +0 -0
  40. {maidr-0.14.0 → maidr-0.16.0}/maidr/util/__init__.py +0 -0
  41. {maidr-0.14.0 → maidr-0.16.0}/maidr/util/environment.py +0 -0
  42. {maidr-0.14.0 → maidr-0.16.0}/maidr/util/mixin/__init__.py +0 -0
  43. {maidr-0.14.0 → maidr-0.16.0}/maidr/util/mixin/merger_mixin.py +0 -0
  44. {maidr-0.14.0 → maidr-0.16.0}/maidr/widget/__init__.py +0 -0
  45. {maidr-0.14.0 → maidr-0.16.0}/maidr/widget/shiny.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: maidr
3
- Version: 0.14.0
3
+ Version: 0.16.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
@@ -1,4 +1,4 @@
1
- __version__ = "0.14.0"
1
+ __version__ = "0.16.0"
2
2
 
3
3
  from .api import close, render, save_html, set_engine, show, stacked
4
4
  from .core import Maidr
@@ -1,6 +1,7 @@
1
1
  from __future__ import annotations
2
- from typing import Any
2
+
3
3
  import threading
4
+ from typing import Any
4
5
 
5
6
  from matplotlib.artist import Artist
6
7
  from matplotlib.axes import Axes
@@ -57,17 +58,16 @@ class FigureManager:
57
58
  raise ValueError(f"No figure found for axis: {ax}.")
58
59
 
59
60
  # Add plot to the Maidr object associated with the plot's figure.
60
- maidr = cls._get_maidr(ax.get_figure())
61
+ maidr = cls._get_maidr(ax.get_figure(), plot_type)
61
62
  plot = MaidrPlotFactory.create(ax, plot_type, **kwargs)
62
63
  maidr.plots.append(plot)
63
-
64
64
  return maidr
65
65
 
66
66
  @classmethod
67
- def _get_maidr(cls, fig: Figure) -> Maidr:
67
+ def _get_maidr(cls, fig: Figure, plot_type: PlotType) -> Maidr:
68
68
  """Retrieve or create a Maidr instance for the given Figure."""
69
69
  if fig not in cls.figs.keys():
70
- cls.figs[fig] = Maidr(fig)
70
+ cls.figs[fig] = Maidr(fig, plot_type)
71
71
  return cls.figs[fig]
72
72
 
73
73
  @classmethod
@@ -14,6 +14,7 @@ from matplotlib.figure import Figure
14
14
 
15
15
  from maidr.core.context_manager import HighlightContextManager
16
16
  from maidr.core.enum.maidr_key import MaidrKey
17
+ from maidr.core.enum.plot_type import PlotType
17
18
  from maidr.core.plot import MaidrPlot
18
19
  from maidr.util.environment import Environment
19
20
 
@@ -39,12 +40,13 @@ class Maidr:
39
40
  Displays the rendered HTML content in the specified rendering context.
40
41
  """
41
42
 
42
- def __init__(self, fig: Figure) -> None:
43
+ def __init__(self, fig: Figure, plot_type: PlotType = PlotType.LINE) -> None:
43
44
  """Create a new Maidr for the given ``matplotlib.figure.Figure``."""
44
45
  self._fig = fig
45
46
  self._plots = []
46
47
  self.maidr_id = None
47
48
  self.selector_id = Maidr._unique_id()
49
+ self.plot_type = plot_type
48
50
 
49
51
  @property
50
52
  def fig(self) -> Figure:
@@ -137,6 +139,8 @@ class Maidr:
137
139
 
138
140
  def _flatten_maidr(self) -> dict | list[dict]:
139
141
  """Return a single plot schema or a list of schemas from the Maidr instance."""
142
+ if self.plot_type == PlotType.LINE:
143
+ self._plots = [self._plots[0]]
140
144
  maidr = [plot.schema for plot in self._plots]
141
145
 
142
146
  # Replace the selector having maidr='true' with maidr={self.maidr_id}
@@ -16,7 +16,7 @@ from maidr.util.mixin import (
16
16
  class GroupedBarPlot(
17
17
  MaidrPlot, ContainerExtractorMixin, LevelExtractorMixin, DictMergerMixin
18
18
  ):
19
- def __init__(self, ax: Axes, plot_type: PlotType) -> None:
19
+ def __init__(self, ax: Axes, plot_type: PlotType, **kwargs) -> None:
20
20
  super().__init__(ax, plot_type)
21
21
  self._support_highlighting = False
22
22
 
@@ -0,0 +1,102 @@
1
+ from matplotlib.axes import Axes
2
+ from matplotlib.lines import Line2D
3
+
4
+ from maidr.core.enum.maidr_key import MaidrKey
5
+ from maidr.core.enum.plot_type import PlotType
6
+ from maidr.core.plot.maidr_plot import MaidrPlot
7
+ from maidr.exception.extraction_error import ExtractionError
8
+ from maidr.util.environment import Environment
9
+ from maidr.util.mixin.extractor_mixin import LineExtractorMixin
10
+
11
+
12
+ class MultiLinePlot(MaidrPlot, LineExtractorMixin):
13
+ """
14
+ A class for extracting and processing data from line plots.
15
+
16
+ This class can handle both single-line and multi-line plots, extracting
17
+ coordinate data and line identifiers. It processes matplotlib Line2D objects
18
+ and converts them into structured data for further processing or visualization.
19
+
20
+ Parameters
21
+ ----------
22
+ ax : Axes
23
+ The matplotlib axes object containing the line plot(s).
24
+ **kwargs : dict
25
+ Additional keyword arguments to pass to the parent class.
26
+
27
+ Attributes
28
+ ----------
29
+ type : PlotType
30
+ Set to PlotType.LINE to identify this as a line plot.
31
+
32
+ Notes
33
+ -----
34
+ - When using the JavaScript engine, only single-line plots are supported.
35
+ - For multi-line plots, use the TypeScript engine.
36
+ - The extracted data structure includes x, y coordinates and line identifiers
37
+ (fill values) for each point.
38
+ """
39
+
40
+ def __init__(self, ax: Axes, **kwargs):
41
+ super().__init__(ax, PlotType.LINE)
42
+
43
+ def _get_selector(self) -> str:
44
+ return "g[maidr='true'] > path"
45
+
46
+ def _extract_plot_data(self) -> list[dict]:
47
+ plot = self.extract_lines(self.ax)
48
+ data = self._extract_line_data(plot)
49
+ engine = Environment.get_engine()
50
+ if engine == "js":
51
+ if len(data) > 1:
52
+ raise Exception(
53
+ "MultiLine Plot not supported in JS. Use TypeScript Engine for this plot!"
54
+ )
55
+ data = data[0]
56
+
57
+ if data is None:
58
+ raise ExtractionError(self.type, plot)
59
+
60
+ return data
61
+
62
+ def _extract_line_data(self, plot: list[Line2D] | None) -> list[dict] | None:
63
+ """
64
+ Extract data from multiple line objects.
65
+
66
+ Parameters
67
+ ----------
68
+ plot : list[Line2D] | None
69
+ List of Line2D objects to extract data from.
70
+
71
+ Returns
72
+ -------
73
+ list[dict] | None
74
+ List of dictionaries containing x,y coordinates and line identifiers,
75
+ or None if the plot data is invalid.
76
+ """
77
+ if plot is None or len(plot) == 0:
78
+ return None
79
+
80
+ all_line_data = []
81
+
82
+ # Process each line in the plot
83
+ for i, line in enumerate(plot):
84
+ if line.get_xydata() is None:
85
+ continue
86
+
87
+ # Tag the element for highlighting
88
+ self._elements.append(line)
89
+
90
+ # Extract data from this line
91
+ line_data = [
92
+ {
93
+ MaidrKey.X: float(x),
94
+ MaidrKey.Y: float(y),
95
+ MaidrKey.FILL: line.get_label(),
96
+ }
97
+ for x, y in line.get_xydata() # type: ignore
98
+ ]
99
+
100
+ all_line_data.append(line_data)
101
+
102
+ return all_line_data if all_line_data else None
@@ -8,7 +8,7 @@ from maidr.core.plot.boxplot import BoxPlot
8
8
  from maidr.core.plot.grouped_barplot import GroupedBarPlot
9
9
  from maidr.core.plot.heatmap import HeatPlot
10
10
  from maidr.core.plot.histogram import HistPlot
11
- from maidr.core.plot.lineplot import LinePlot
11
+ from maidr.core.plot.lineplot import MultiLinePlot
12
12
  from maidr.core.plot.maidr_plot import MaidrPlot
13
13
  from maidr.core.plot.scatterplot import ScatterPlot
14
14
 
@@ -39,7 +39,7 @@ class MaidrPlotFactory:
39
39
  elif PlotType.HIST == plot_type:
40
40
  return HistPlot(ax)
41
41
  elif PlotType.LINE == plot_type:
42
- return LinePlot(ax)
42
+ return MultiLinePlot(ax)
43
43
  elif PlotType.SCATTER == plot_type:
44
44
  return ScatterPlot(ax)
45
45
  elif PlotType.DODGED == plot_type or PlotType.STACKED == plot_type:
@@ -0,0 +1,38 @@
1
+ from __future__ import annotations
2
+
3
+ import wrapt
4
+ from matplotlib.axes import Axes
5
+ from matplotlib.lines import Line2D
6
+
7
+ from maidr.core.enum import PlotType
8
+ from maidr.patch.common import common
9
+
10
+
11
+ def line(wrapped, instance, args, kwargs) -> Axes | list[Line2D]:
12
+ """
13
+ Wrapper function for line plotting functions in matplotlib and seaborn.
14
+
15
+ Parameters
16
+ ----------
17
+ wrapped : callable
18
+ The wrapped function (plot or lineplot)
19
+ instance : object
20
+ The object to which the wrapped function belongs
21
+ args : tuple
22
+ Positional arguments passed to the wrapped function
23
+ kwargs : dict
24
+ Keyword arguments passed to the wrapped function
25
+
26
+ Returns
27
+ -------
28
+ Axes | list[Line2D]
29
+ The result of the wrapped function after processing
30
+ """
31
+ return common(PlotType.LINE, wrapped, instance, args, kwargs)
32
+
33
+
34
+ # Patch matplotlib function.
35
+ wrapt.wrap_function_wrapper(Axes, "plot", line)
36
+
37
+ # Patch seaborn function.
38
+ wrapt.wrap_function_wrapper("seaborn", "lineplot", line)
@@ -1,4 +1,5 @@
1
1
  from __future__ import annotations
2
+
2
3
  from typing import Any
3
4
 
4
5
  from matplotlib.axes import Axes
@@ -64,6 +65,16 @@ class LineExtractorMixin:
64
65
  # `maidr` package supports the same.
65
66
  return ax.get_lines()[-1]
66
67
 
68
+ @staticmethod
69
+ def extract_lines(ax: Axes) -> list[Line2D] | None:
70
+ """Retrieve all line objects from Axes, if available."""
71
+ if ax is None or ax.get_lines() is None:
72
+ return None
73
+
74
+ # Since the upstream MaidrJS library currently supports only the last plot line,
75
+ # `maidr` package supports the same.
76
+ return ax.get_lines()
77
+
67
78
 
68
79
  class CollectionExtractorMixin:
69
80
  @staticmethod
@@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api"
4
4
 
5
5
  [tool.poetry]
6
6
  name = "maidr"
7
- version = "0.14.0"
7
+ version = "0.16.0"
8
8
  description = "Multimodal Access and Interactive Data Representations"
9
9
  authors = [
10
10
  "JooYoung Seo <jseo1005@illinois.edu>",
@@ -1,45 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from matplotlib.axes import Axes
4
- from matplotlib.lines import Line2D
5
-
6
- from maidr.core.enum import MaidrKey, PlotType
7
- from maidr.core.plot import MaidrPlot
8
- from maidr.exception import ExtractionError
9
- from maidr.util.environment import Environment
10
- from maidr.util.mixin import LineExtractorMixin
11
-
12
-
13
- class LinePlot(MaidrPlot, LineExtractorMixin):
14
- def __init__(self, ax: Axes) -> None:
15
- super().__init__(ax, PlotType.LINE)
16
-
17
- def _get_selector(self) -> str:
18
- return "g[maidr='true'] > path"
19
-
20
- def _extract_plot_data(self) -> list[dict]:
21
- plot = self.extract_line(self.ax)
22
- data = self._extract_line_data(plot)
23
- engine = Environment.get_engine()
24
- if engine == "ts":
25
- data = [data]
26
-
27
- if data is None:
28
- raise ExtractionError(self.type, plot)
29
-
30
- return data
31
-
32
- def _extract_line_data(self, plot: Line2D | None) -> list[dict] | None:
33
- if plot is None or plot.get_xydata() is None:
34
- return None
35
-
36
- # Tag the elements for highlighting.
37
- self._elements.append(plot)
38
-
39
- return [
40
- {
41
- MaidrKey.X: float(x),
42
- MaidrKey.Y: float(y),
43
- }
44
- for x, y in plot.get_xydata()
45
- ]
@@ -1,20 +0,0 @@
1
- from __future__ import annotations
2
-
3
- import wrapt
4
-
5
- from matplotlib.axes import Axes
6
- from matplotlib.lines import Line2D
7
-
8
- from maidr.core.enum import PlotType
9
- from maidr.patch.common import common
10
-
11
-
12
- def line(wrapped, instance, args, kwargs) -> Axes | list[Line2D]:
13
- return common(PlotType.LINE, wrapped, instance, args, kwargs)
14
-
15
-
16
- # Patch matplotlib function.
17
- wrapt.wrap_function_wrapper(Axes, "plot", line)
18
-
19
- # Patch seaborn function.
20
- wrapt.wrap_function_wrapper("seaborn", "lineplot", line)
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