maidr 1.4.0__tar.gz → 1.4.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.
- {maidr-1.4.0 → maidr-1.4.1}/PKG-INFO +1 -1
- {maidr-1.4.0 → maidr-1.4.1}/maidr/__init__.py +1 -1
- {maidr-1.4.0 → maidr-1.4.1}/maidr/core/maidr.py +74 -7
- {maidr-1.4.0 → maidr-1.4.1}/maidr/core/plot/candlestick.py +28 -4
- {maidr-1.4.0 → maidr-1.4.1}/maidr/core/plot/mplfinance_barplot.py +24 -0
- {maidr-1.4.0 → maidr-1.4.1}/maidr/core/plot/mplfinance_lineplot.py +129 -2
- {maidr-1.4.0 → maidr-1.4.1}/maidr/patch/mplfinance.py +3 -1
- {maidr-1.4.0 → maidr-1.4.1}/pyproject.toml +1 -1
- {maidr-1.4.0 → maidr-1.4.1}/LICENSE +0 -0
- {maidr-1.4.0 → maidr-1.4.1}/README.md +0 -0
- {maidr-1.4.0 → maidr-1.4.1}/maidr/api.py +0 -0
- {maidr-1.4.0 → maidr-1.4.1}/maidr/core/__init__.py +0 -0
- {maidr-1.4.0 → maidr-1.4.1}/maidr/core/context_manager.py +0 -0
- {maidr-1.4.0 → maidr-1.4.1}/maidr/core/enum/__init__.py +0 -0
- {maidr-1.4.0 → maidr-1.4.1}/maidr/core/enum/library.py +0 -0
- {maidr-1.4.0 → maidr-1.4.1}/maidr/core/enum/maidr_key.py +0 -0
- {maidr-1.4.0 → maidr-1.4.1}/maidr/core/enum/plot_type.py +0 -0
- {maidr-1.4.0 → maidr-1.4.1}/maidr/core/enum/smooth_keywords.py +0 -0
- {maidr-1.4.0 → maidr-1.4.1}/maidr/core/figure_manager.py +0 -0
- {maidr-1.4.0 → maidr-1.4.1}/maidr/core/plot/__init__.py +0 -0
- {maidr-1.4.0 → maidr-1.4.1}/maidr/core/plot/barplot.py +0 -0
- {maidr-1.4.0 → maidr-1.4.1}/maidr/core/plot/boxplot.py +0 -0
- {maidr-1.4.0 → maidr-1.4.1}/maidr/core/plot/grouped_barplot.py +0 -0
- {maidr-1.4.0 → maidr-1.4.1}/maidr/core/plot/heatmap.py +0 -0
- {maidr-1.4.0 → maidr-1.4.1}/maidr/core/plot/histogram.py +0 -0
- {maidr-1.4.0 → maidr-1.4.1}/maidr/core/plot/lineplot.py +0 -0
- {maidr-1.4.0 → maidr-1.4.1}/maidr/core/plot/maidr_plot.py +0 -0
- {maidr-1.4.0 → maidr-1.4.1}/maidr/core/plot/maidr_plot_factory.py +0 -0
- {maidr-1.4.0 → maidr-1.4.1}/maidr/core/plot/regplot.py +0 -0
- {maidr-1.4.0 → maidr-1.4.1}/maidr/core/plot/scatterplot.py +0 -0
- {maidr-1.4.0 → maidr-1.4.1}/maidr/exception/__init__.py +0 -0
- {maidr-1.4.0 → maidr-1.4.1}/maidr/exception/extraction_error.py +0 -0
- {maidr-1.4.0 → maidr-1.4.1}/maidr/patch/__init__.py +0 -0
- {maidr-1.4.0 → maidr-1.4.1}/maidr/patch/barplot.py +0 -0
- {maidr-1.4.0 → maidr-1.4.1}/maidr/patch/boxplot.py +0 -0
- {maidr-1.4.0 → maidr-1.4.1}/maidr/patch/candlestick.py +0 -0
- {maidr-1.4.0 → maidr-1.4.1}/maidr/patch/clear.py +0 -0
- {maidr-1.4.0 → maidr-1.4.1}/maidr/patch/common.py +0 -0
- {maidr-1.4.0 → maidr-1.4.1}/maidr/patch/heatmap.py +0 -0
- {maidr-1.4.0 → maidr-1.4.1}/maidr/patch/highlight.py +0 -0
- {maidr-1.4.0 → maidr-1.4.1}/maidr/patch/histogram.py +0 -0
- {maidr-1.4.0 → maidr-1.4.1}/maidr/patch/kdeplot.py +0 -0
- {maidr-1.4.0 → maidr-1.4.1}/maidr/patch/lineplot.py +0 -0
- {maidr-1.4.0 → maidr-1.4.1}/maidr/patch/regplot.py +0 -0
- {maidr-1.4.0 → maidr-1.4.1}/maidr/patch/scatterplot.py +0 -0
- {maidr-1.4.0 → maidr-1.4.1}/maidr/util/__init__.py +0 -0
- {maidr-1.4.0 → maidr-1.4.1}/maidr/util/dedup_utils.py +0 -0
- {maidr-1.4.0 → maidr-1.4.1}/maidr/util/environment.py +0 -0
- {maidr-1.4.0 → maidr-1.4.1}/maidr/util/mixin/__init__.py +0 -0
- {maidr-1.4.0 → maidr-1.4.1}/maidr/util/mixin/extractor_mixin.py +0 -0
- {maidr-1.4.0 → maidr-1.4.1}/maidr/util/mixin/merger_mixin.py +0 -0
- {maidr-1.4.0 → maidr-1.4.1}/maidr/util/mplfinance_utils.py +0 -0
- {maidr-1.4.0 → maidr-1.4.1}/maidr/util/plot_detection.py +0 -0
- {maidr-1.4.0 → maidr-1.4.1}/maidr/util/regression_line_utils.py +0 -0
- {maidr-1.4.0 → maidr-1.4.1}/maidr/util/svg_utils.py +0 -0
- {maidr-1.4.0 → maidr-1.4.1}/maidr/widget/__init__.py +0 -0
- {maidr-1.4.0 → maidr-1.4.1}/maidr/widget/shiny.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: maidr
|
|
3
|
-
Version: 1.4.
|
|
3
|
+
Version: 1.4.1
|
|
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,6 +1,9 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
from datetime import datetime
|
|
4
|
+
import urllib.request
|
|
5
|
+
import urllib.error
|
|
6
|
+
import json
|
|
4
7
|
|
|
5
8
|
import io
|
|
6
9
|
import json
|
|
@@ -22,6 +25,11 @@ from maidr.core.plot import MaidrPlot
|
|
|
22
25
|
from maidr.util.environment import Environment
|
|
23
26
|
from maidr.util.dedup_utils import deduplicate_smooth_and_line
|
|
24
27
|
|
|
28
|
+
# Module-level cache for version to avoid repeated API calls
|
|
29
|
+
_MAIDR_VERSION_CACHE: str | None = None
|
|
30
|
+
_MAIDR_VERSION_CACHE_TIME: float = 0.0
|
|
31
|
+
_MAIDR_CACHE_DURATION = 3600 # Cache for 1 hour
|
|
32
|
+
|
|
25
33
|
|
|
26
34
|
class Maidr:
|
|
27
35
|
"""
|
|
@@ -34,6 +42,8 @@ class Maidr:
|
|
|
34
42
|
The matplotlib figure associated with this instance.
|
|
35
43
|
_plots : list[MaidrPlot]
|
|
36
44
|
A list of MaidrPlot objects which hold additional plot-specific configurations.
|
|
45
|
+
_cached_version : str | None
|
|
46
|
+
Cached version of maidr from npm registry to avoid repeated API calls.
|
|
37
47
|
|
|
38
48
|
Methods
|
|
39
49
|
-------
|
|
@@ -271,20 +281,77 @@ class Maidr:
|
|
|
271
281
|
"""Generate a unique identifier string using UUID4."""
|
|
272
282
|
return str(uuid.uuid4())
|
|
273
283
|
|
|
284
|
+
@staticmethod
|
|
285
|
+
def _get_latest_maidr_version() -> str:
|
|
286
|
+
"""
|
|
287
|
+
Query the npm registry API to get the latest version of maidr with caching.
|
|
288
|
+
|
|
289
|
+
Returns
|
|
290
|
+
-------
|
|
291
|
+
str
|
|
292
|
+
The latest version of maidr from npm registry, or 'latest' as fallback.
|
|
293
|
+
"""
|
|
294
|
+
import time
|
|
295
|
+
|
|
296
|
+
global _MAIDR_VERSION_CACHE, _MAIDR_VERSION_CACHE_TIME
|
|
297
|
+
|
|
298
|
+
# Check if version fetching is disabled via environment variable
|
|
299
|
+
if os.getenv("MAIDR_DISABLE_VERSION_FETCH", "").lower() in ("true", "1", "yes"):
|
|
300
|
+
return "latest"
|
|
301
|
+
|
|
302
|
+
current_time = time.time()
|
|
303
|
+
|
|
304
|
+
# Check if we have a valid cached version
|
|
305
|
+
if (
|
|
306
|
+
_MAIDR_VERSION_CACHE is not None
|
|
307
|
+
and current_time - _MAIDR_VERSION_CACHE_TIME < _MAIDR_CACHE_DURATION
|
|
308
|
+
):
|
|
309
|
+
return _MAIDR_VERSION_CACHE
|
|
310
|
+
|
|
311
|
+
try:
|
|
312
|
+
# Query npm registry API for maidr package
|
|
313
|
+
with urllib.request.urlopen(
|
|
314
|
+
"https://registry.npmjs.org/maidr/latest", timeout=5 # 5 second timeout
|
|
315
|
+
) as response:
|
|
316
|
+
if response.status == 200:
|
|
317
|
+
data = json.loads(response.read().decode("utf-8"))
|
|
318
|
+
version = data.get("version", "latest")
|
|
319
|
+
|
|
320
|
+
# Cache the successful result
|
|
321
|
+
_MAIDR_VERSION_CACHE = version
|
|
322
|
+
_MAIDR_VERSION_CACHE_TIME = current_time
|
|
323
|
+
|
|
324
|
+
return version
|
|
325
|
+
|
|
326
|
+
except Exception:
|
|
327
|
+
# Any error - just use latest
|
|
328
|
+
pass
|
|
329
|
+
|
|
330
|
+
# Fallback to 'latest' if API call fails
|
|
331
|
+
return "latest"
|
|
332
|
+
|
|
333
|
+
@staticmethod
|
|
334
|
+
def clear_version_cache() -> None:
|
|
335
|
+
"""Clear the cached version to force a fresh API call on next request."""
|
|
336
|
+
global _MAIDR_VERSION_CACHE, _MAIDR_VERSION_CACHE_TIME
|
|
337
|
+
_MAIDR_VERSION_CACHE = None
|
|
338
|
+
_MAIDR_VERSION_CACHE_TIME = 0.0
|
|
339
|
+
|
|
274
340
|
@staticmethod
|
|
275
341
|
def _inject_plot(plot: HTML, maidr: str, maidr_id, use_iframe: bool = True) -> Tag:
|
|
276
342
|
"""Embed the plot and associated MAIDR scripts into the HTML structure."""
|
|
277
|
-
#
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
343
|
+
# Get the latest version from npm registry
|
|
344
|
+
latest_version = Maidr._get_latest_maidr_version()
|
|
345
|
+
MAIDR_TS_CDN_URL = (
|
|
346
|
+
f"https://cdn.jsdelivr.net/npm/maidr@{latest_version}/dist/maidr.js"
|
|
347
|
+
)
|
|
281
348
|
|
|
282
349
|
script = f"""
|
|
283
|
-
if (!document.querySelector('script[src="{MAIDR_TS_CDN_URL}
|
|
350
|
+
if (!document.querySelector('script[src="{MAIDR_TS_CDN_URL}"]'))
|
|
284
351
|
{{
|
|
285
352
|
var script = document.createElement('script');
|
|
286
353
|
script.type = 'module';
|
|
287
|
-
script.src = '{MAIDR_TS_CDN_URL}
|
|
354
|
+
script.src = '{MAIDR_TS_CDN_URL}';
|
|
288
355
|
script.addEventListener('load', function() {{
|
|
289
356
|
window.main();
|
|
290
357
|
}});
|
|
@@ -299,7 +366,7 @@ class Maidr:
|
|
|
299
366
|
base_html = tags.div(
|
|
300
367
|
tags.link(
|
|
301
368
|
rel="stylesheet",
|
|
302
|
-
href="https://cdn.jsdelivr.net/npm/maidr/dist/maidr_style.css",
|
|
369
|
+
href=f"https://cdn.jsdelivr.net/npm/maidr@{latest_version}/dist/maidr_style.css",
|
|
303
370
|
),
|
|
304
371
|
tags.script(script, type="text/javascript"),
|
|
305
372
|
tags.div(plot),
|
|
@@ -1,15 +1,24 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
import matplotlib.dates as mdates
|
|
2
4
|
import numpy as np
|
|
3
5
|
from matplotlib.axes import Axes
|
|
4
6
|
from matplotlib.patches import Rectangle
|
|
5
7
|
|
|
6
|
-
from maidr.core.enum
|
|
7
|
-
from maidr.core.plot
|
|
8
|
+
from maidr.core.enum import PlotType
|
|
9
|
+
from maidr.core.plot import MaidrPlot
|
|
8
10
|
from maidr.core.enum.maidr_key import MaidrKey
|
|
9
11
|
from maidr.util.mplfinance_utils import MplfinanceDataExtractor
|
|
10
12
|
|
|
11
13
|
|
|
12
14
|
class CandlestickPlot(MaidrPlot):
|
|
15
|
+
"""
|
|
16
|
+
Specialized candlestick plot class for mplfinance OHLC data.
|
|
17
|
+
|
|
18
|
+
This class handles the extraction and processing of candlestick data from mplfinance
|
|
19
|
+
plots, including proper date conversion and data validation.
|
|
20
|
+
"""
|
|
21
|
+
|
|
13
22
|
def __init__(self, axes: list[Axes], **kwargs) -> None:
|
|
14
23
|
"""
|
|
15
24
|
Initialize the CandlestickPlot.
|
|
@@ -93,7 +102,20 @@ class CandlestickPlot(MaidrPlot):
|
|
|
93
102
|
return []
|
|
94
103
|
|
|
95
104
|
def _extract_axes_data(self) -> dict:
|
|
96
|
-
|
|
105
|
+
"""
|
|
106
|
+
Extract the plot's axes data including labels.
|
|
107
|
+
|
|
108
|
+
Returns
|
|
109
|
+
-------
|
|
110
|
+
dict
|
|
111
|
+
Dictionary containing x and y axis labels.
|
|
112
|
+
"""
|
|
113
|
+
x_labels = self.ax.get_xlabel()
|
|
114
|
+
if not x_labels:
|
|
115
|
+
x_labels = self.extract_shared_xlabel(self.ax)
|
|
116
|
+
if not x_labels:
|
|
117
|
+
x_labels = "X"
|
|
118
|
+
return {MaidrKey.X: x_labels, MaidrKey.Y: self.ax.get_ylabel()}
|
|
97
119
|
|
|
98
120
|
def _get_selector(self) -> str:
|
|
99
121
|
"""Return the CSS selector for highlighting candlestick elements in the SVG output."""
|
|
@@ -109,9 +131,11 @@ class CandlestickPlot(MaidrPlot):
|
|
|
109
131
|
|
|
110
132
|
def render(self) -> dict:
|
|
111
133
|
"""Initialize the MAIDR schema dictionary with basic plot information."""
|
|
134
|
+
title = "Candlestick Chart"
|
|
135
|
+
|
|
112
136
|
maidr_schema = {
|
|
113
137
|
MaidrKey.TYPE: self.type,
|
|
114
|
-
MaidrKey.TITLE:
|
|
138
|
+
MaidrKey.TITLE: title,
|
|
115
139
|
MaidrKey.AXES: self._extract_axes_data(),
|
|
116
140
|
MaidrKey.DATA: self._extract_plot_data(),
|
|
117
141
|
}
|
|
@@ -30,6 +30,11 @@ class MplfinanceBarPlot(
|
|
|
30
30
|
self._custom_patches = kwargs.get("_maidr_patches", None)
|
|
31
31
|
# Store date numbers for volume bars (from mplfinance)
|
|
32
32
|
self._maidr_date_nums = kwargs.get("_maidr_date_nums", None)
|
|
33
|
+
# Store custom title
|
|
34
|
+
|
|
35
|
+
def set_title(self, title: str) -> None:
|
|
36
|
+
"""Set a custom title for this volume bar plot."""
|
|
37
|
+
self._title = title
|
|
33
38
|
|
|
34
39
|
def _extract_plot_data(self) -> list:
|
|
35
40
|
"""Extract data from mplfinance volume patches."""
|
|
@@ -113,3 +118,22 @@ class MplfinanceBarPlot(
|
|
|
113
118
|
# Use the standard working selector that gets replaced with UUID by Maidr class
|
|
114
119
|
# This works for both original bar plots and mplfinance volume bars
|
|
115
120
|
return "g[maidr='true'] > path"
|
|
121
|
+
|
|
122
|
+
def render(self) -> dict:
|
|
123
|
+
"""Initialize the MAIDR schema dictionary with basic plot information."""
|
|
124
|
+
from maidr.core.enum.maidr_key import MaidrKey
|
|
125
|
+
|
|
126
|
+
title = "Volume Bar Plot"
|
|
127
|
+
|
|
128
|
+
maidr_schema = {
|
|
129
|
+
MaidrKey.TYPE: self.type,
|
|
130
|
+
MaidrKey.TITLE: title,
|
|
131
|
+
MaidrKey.AXES: self._extract_axes_data(),
|
|
132
|
+
MaidrKey.DATA: self._extract_plot_data(),
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
# Include selector only if the plot supports highlighting.
|
|
136
|
+
if self._support_highlighting:
|
|
137
|
+
maidr_schema[MaidrKey.SELECTOR] = self._get_selector()
|
|
138
|
+
|
|
139
|
+
return maidr_schema
|
|
@@ -23,6 +23,7 @@ class MplfinanceLinePlot(MaidrPlot, LineExtractorMixin):
|
|
|
23
23
|
|
|
24
24
|
def __init__(self, ax: Axes, **kwargs):
|
|
25
25
|
super().__init__(ax, PlotType.LINE)
|
|
26
|
+
self._line_titles = [] # Store line titles separately
|
|
26
27
|
|
|
27
28
|
def _get_selector(self) -> Union[str, List[str]]:
|
|
28
29
|
"""Return selectors for all lines that have data."""
|
|
@@ -47,6 +48,65 @@ class MplfinanceLinePlot(MaidrPlot, LineExtractorMixin):
|
|
|
47
48
|
|
|
48
49
|
return selectors
|
|
49
50
|
|
|
51
|
+
def _extract_axes_data(self) -> dict:
|
|
52
|
+
"""
|
|
53
|
+
Extract axis labels for the plot.
|
|
54
|
+
|
|
55
|
+
Returns
|
|
56
|
+
-------
|
|
57
|
+
dict
|
|
58
|
+
Dictionary containing x and y axis labels with custom y-label for moving averages.
|
|
59
|
+
"""
|
|
60
|
+
x_labels = self.ax.get_xlabel()
|
|
61
|
+
if not x_labels:
|
|
62
|
+
x_labels = self.extract_shared_xlabel(self.ax)
|
|
63
|
+
if not x_labels:
|
|
64
|
+
x_labels = "Date"
|
|
65
|
+
|
|
66
|
+
# Get the period from the first line for y-axis label
|
|
67
|
+
ma_period = self._extract_moving_average_period()
|
|
68
|
+
y_label = (
|
|
69
|
+
f"{ma_period}-day mav price ($)"
|
|
70
|
+
if ma_period
|
|
71
|
+
else "Moving Average Price ($)"
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
return {MaidrKey.X: x_labels, MaidrKey.Y: y_label}
|
|
75
|
+
|
|
76
|
+
def _extract_moving_average_periods(self) -> List[str]:
|
|
77
|
+
"""
|
|
78
|
+
Extract all moving average periods from the _maidr_ma_period attributes set by the mplfinance patch.
|
|
79
|
+
|
|
80
|
+
Returns
|
|
81
|
+
-------
|
|
82
|
+
List[str]
|
|
83
|
+
List of moving average periods (e.g., ["3", "6", "30"]).
|
|
84
|
+
"""
|
|
85
|
+
all_lines = self.ax.get_lines()
|
|
86
|
+
periods = []
|
|
87
|
+
for line in all_lines:
|
|
88
|
+
# Get the period that was stored by the mplfinance patch
|
|
89
|
+
ma_period = getattr(line, "_maidr_ma_period", None)
|
|
90
|
+
if ma_period is not None:
|
|
91
|
+
periods.append(str(ma_period))
|
|
92
|
+
|
|
93
|
+
# Remove duplicates and sort
|
|
94
|
+
periods = sorted(list(set(periods)))
|
|
95
|
+
|
|
96
|
+
return periods
|
|
97
|
+
|
|
98
|
+
def _extract_moving_average_period(self) -> str:
|
|
99
|
+
"""
|
|
100
|
+
Extract the moving average period from the _maidr_ma_period attribute set by the mplfinance patch.
|
|
101
|
+
|
|
102
|
+
Returns
|
|
103
|
+
-------
|
|
104
|
+
str
|
|
105
|
+
The moving average period (e.g., "3", "6", "30") or empty string if no period found.
|
|
106
|
+
"""
|
|
107
|
+
periods = self._extract_moving_average_periods()
|
|
108
|
+
return periods[0] if periods else ""
|
|
109
|
+
|
|
50
110
|
def _extract_plot_data(self) -> Union[List[List[dict]], None]:
|
|
51
111
|
"""Extract data from mplfinance moving average lines."""
|
|
52
112
|
data = self._extract_line_data()
|
|
@@ -91,6 +151,17 @@ class MplfinanceLinePlot(MaidrPlot, LineExtractorMixin):
|
|
|
91
151
|
line.set_gid(unique_gid)
|
|
92
152
|
|
|
93
153
|
label: str = line.get_label() # type: ignore
|
|
154
|
+
|
|
155
|
+
# Get the period for this specific line
|
|
156
|
+
ma_period = getattr(line, "_maidr_ma_period", None)
|
|
157
|
+
|
|
158
|
+
# Create title for this line
|
|
159
|
+
line_title = (
|
|
160
|
+
f"{ma_period}-Day Moving Average Line Plot"
|
|
161
|
+
if ma_period
|
|
162
|
+
else "Moving Average Line Plot"
|
|
163
|
+
)
|
|
164
|
+
|
|
94
165
|
line_data = []
|
|
95
166
|
|
|
96
167
|
# Check if this line has date numbers from mplfinance
|
|
@@ -117,12 +188,22 @@ class MplfinanceLinePlot(MaidrPlot, LineExtractorMixin):
|
|
|
117
188
|
point_data = {
|
|
118
189
|
MaidrKey.X: x_value,
|
|
119
190
|
MaidrKey.Y: float(y),
|
|
120
|
-
MaidrKey.FILL: (label if not label.startswith("_child") else ""),
|
|
121
191
|
}
|
|
122
192
|
line_data.append(point_data)
|
|
123
193
|
|
|
124
194
|
if line_data:
|
|
125
|
-
|
|
195
|
+
# Create line data with title, axes, and points structure
|
|
196
|
+
line_with_metadata = {
|
|
197
|
+
"title": line_title,
|
|
198
|
+
"axes": {
|
|
199
|
+
"x": "Date",
|
|
200
|
+
"y": f"{ma_period}-day mav price ($)"
|
|
201
|
+
if ma_period
|
|
202
|
+
else "Moving Average Price ($)",
|
|
203
|
+
},
|
|
204
|
+
"points": line_data,
|
|
205
|
+
}
|
|
206
|
+
all_lines_data.append(line_with_metadata)
|
|
126
207
|
|
|
127
208
|
return all_lines_data if all_lines_data else None
|
|
128
209
|
|
|
@@ -144,3 +225,49 @@ class MplfinanceLinePlot(MaidrPlot, LineExtractorMixin):
|
|
|
144
225
|
Date string in YYYY-MM-DD format
|
|
145
226
|
"""
|
|
146
227
|
return MplfinanceDataExtractor._convert_date_num_to_string(x_value)
|
|
228
|
+
|
|
229
|
+
def _extract_line_titles(self) -> List[str]:
|
|
230
|
+
"""
|
|
231
|
+
Extract titles for all moving average lines.
|
|
232
|
+
|
|
233
|
+
Returns
|
|
234
|
+
-------
|
|
235
|
+
List[str]
|
|
236
|
+
List of titles for each line.
|
|
237
|
+
"""
|
|
238
|
+
all_lines = self.ax.get_lines()
|
|
239
|
+
titles = []
|
|
240
|
+
|
|
241
|
+
for line in all_lines:
|
|
242
|
+
ma_period = getattr(line, "_maidr_ma_period", None)
|
|
243
|
+
title = (
|
|
244
|
+
f"{ma_period}-Day Moving Average Line Plot"
|
|
245
|
+
if ma_period
|
|
246
|
+
else "Moving Average Line Plot"
|
|
247
|
+
)
|
|
248
|
+
titles.append(title)
|
|
249
|
+
|
|
250
|
+
return titles
|
|
251
|
+
|
|
252
|
+
def render(self) -> dict:
|
|
253
|
+
"""Initialize the MAIDR schema dictionary with basic plot information."""
|
|
254
|
+
# Use the first line's period for the main title
|
|
255
|
+
ma_period = self._extract_moving_average_period()
|
|
256
|
+
title = (
|
|
257
|
+
f"{ma_period}-Day Moving Averages Line Plot"
|
|
258
|
+
if ma_period
|
|
259
|
+
else "Moving Averages Line Plot"
|
|
260
|
+
)
|
|
261
|
+
|
|
262
|
+
maidr_schema = {
|
|
263
|
+
MaidrKey.TYPE: self.type,
|
|
264
|
+
MaidrKey.TITLE: title,
|
|
265
|
+
MaidrKey.AXES: self._extract_axes_data(),
|
|
266
|
+
MaidrKey.DATA: self._extract_plot_data(),
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
# Include selector only if the plot supports highlighting.
|
|
270
|
+
if self._support_highlighting:
|
|
271
|
+
maidr_schema[MaidrKey.SELECTOR] = self._get_selector()
|
|
272
|
+
|
|
273
|
+
return maidr_schema
|
|
@@ -8,7 +8,6 @@ from matplotlib.lines import Line2D
|
|
|
8
8
|
from maidr.core.enum import PlotType
|
|
9
9
|
from maidr.patch.common import common
|
|
10
10
|
from maidr.core.context_manager import ContextManager
|
|
11
|
-
from maidr.util.mplfinance_utils import MplfinanceDataExtractor
|
|
12
11
|
|
|
13
12
|
|
|
14
13
|
def mplfinance_plot_patch(wrapped, instance, args, kwargs):
|
|
@@ -150,6 +149,9 @@ def mplfinance_plot_patch(wrapped, instance, args, kwargs):
|
|
|
150
149
|
# Map NaN count to likely moving average period
|
|
151
150
|
estimated_period = nan_count + 1
|
|
152
151
|
|
|
152
|
+
# Store the period directly on the line for easy access
|
|
153
|
+
setattr(line, "_maidr_ma_period", estimated_period)
|
|
154
|
+
|
|
153
155
|
# Create a better label for the line
|
|
154
156
|
label = str(line.get_label())
|
|
155
157
|
if label.startswith("_child"):
|
|
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
|
|
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
|