MatplotLibAPI 3.2.21__tar.gz → 4.0.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.
- matplotlibapi-4.0.0/.github/dependabot.yml +10 -0
- matplotlibapi-4.0.0/.github/workflows/ci.yml +46 -0
- {matplotlibapi-3.2.21 → matplotlibapi-4.0.0}/.github/workflows/python-publish.yml +3 -4
- matplotlibapi-4.0.0/.pre-commit-config.yaml +33 -0
- {matplotlibapi-3.2.21 → matplotlibapi-4.0.0}/AGENTS.md +1 -1
- {matplotlibapi-3.2.21 → matplotlibapi-4.0.0}/PKG-INFO +98 -9
- {matplotlibapi-3.2.21 → matplotlibapi-4.0.0}/README.md +95 -8
- matplotlibapi-4.0.0/examples/__init__.py +9 -0
- matplotlibapi-4.0.0/examples/network.png +0 -0
- matplotlibapi-4.0.0/examples/network.py +41 -0
- {matplotlibapi-3.2.21 → matplotlibapi-4.0.0}/pyproject.toml +17 -2
- matplotlibapi-4.0.0/scripts/pre_commit.sh +71 -0
- matplotlibapi-4.0.0/src/MatplotLibAPI/__init__.py +7 -0
- {matplotlibapi-3.2.21 → matplotlibapi-4.0.0/src}/MatplotLibAPI/accessor.py +519 -196
- matplotlibapi-4.0.0/src/MatplotLibAPI/area.py +177 -0
- matplotlibapi-4.0.0/src/MatplotLibAPI/bar.py +185 -0
- matplotlibapi-4.0.0/src/MatplotLibAPI/base_plot.py +88 -0
- matplotlibapi-4.0.0/src/MatplotLibAPI/box_violin.py +180 -0
- matplotlibapi-4.0.0/src/MatplotLibAPI/bubble.py +568 -0
- matplotlibapi-3.2.21/MatplotLibAPI/Composite.py → matplotlibapi-4.0.0/src/MatplotLibAPI/composite.py +127 -106
- matplotlibapi-4.0.0/src/MatplotLibAPI/heatmap.py +223 -0
- matplotlibapi-4.0.0/src/MatplotLibAPI/histogram.py +170 -0
- matplotlibapi-4.0.0/src/MatplotLibAPI/mcp/__init__.py +17 -0
- matplotlibapi-4.0.0/src/MatplotLibAPI/mcp/metadata.py +90 -0
- matplotlibapi-4.0.0/src/MatplotLibAPI/mcp/renderers.py +45 -0
- matplotlibapi-4.0.0/src/MatplotLibAPI/mcp_server.py +626 -0
- matplotlibapi-4.0.0/src/MatplotLibAPI/network/__init__.py +28 -0
- matplotlibapi-4.0.0/src/MatplotLibAPI/network/constants.py +22 -0
- matplotlibapi-4.0.0/src/MatplotLibAPI/network/core.py +1360 -0
- matplotlibapi-4.0.0/src/MatplotLibAPI/network/plot.py +597 -0
- matplotlibapi-4.0.0/src/MatplotLibAPI/network/scaling.py +56 -0
- matplotlibapi-4.0.0/src/MatplotLibAPI/pie.py +154 -0
- matplotlibapi-4.0.0/src/MatplotLibAPI/pivot.py +274 -0
- matplotlibapi-4.0.0/src/MatplotLibAPI/sankey.py +99 -0
- matplotlibapi-3.2.21/MatplotLibAPI/StyleTemplate.py → matplotlibapi-4.0.0/src/MatplotLibAPI/style_template.py +27 -22
- matplotlibapi-4.0.0/src/MatplotLibAPI/sunburst.py +139 -0
- matplotlibapi-3.2.21/MatplotLibAPI/Table.py → matplotlibapi-4.0.0/src/MatplotLibAPI/table.py +112 -87
- matplotlibapi-3.2.21/MatplotLibAPI/Timeserie.py → matplotlibapi-4.0.0/src/MatplotLibAPI/timeserie.py +98 -42
- matplotlibapi-3.2.21/MatplotLibAPI/Treemap.py → matplotlibapi-4.0.0/src/MatplotLibAPI/treemap.py +43 -55
- matplotlibapi-4.0.0/src/MatplotLibAPI/typing.py +12 -0
- matplotlibapi-3.2.21/MatplotLibAPI/_visualization_utils.py → matplotlibapi-4.0.0/src/MatplotLibAPI/utils.py +7 -13
- matplotlibapi-4.0.0/src/MatplotLibAPI/waffle.py +173 -0
- matplotlibapi-4.0.0/src/MatplotLibAPI/word_cloud.py +489 -0
- {matplotlibapi-3.2.21 → matplotlibapi-4.0.0}/tests/conftest.py +6 -2
- {matplotlibapi-3.2.21 → matplotlibapi-4.0.0}/tests/test_area.py +1 -1
- {matplotlibapi-3.2.21 → matplotlibapi-4.0.0}/tests/test_bar.py +1 -1
- {matplotlibapi-3.2.21 → matplotlibapi-4.0.0}/tests/test_box_violin.py +1 -1
- {matplotlibapi-3.2.21 → matplotlibapi-4.0.0}/tests/test_bubble.py +2 -2
- matplotlibapi-4.0.0/tests/test_composite.py +78 -0
- {matplotlibapi-3.2.21 → matplotlibapi-4.0.0}/tests/test_heatmap.py +5 -3
- {matplotlibapi-3.2.21 → matplotlibapi-4.0.0}/tests/test_histogram.py +2 -4
- matplotlibapi-4.0.0/tests/test_mcp_server.py +186 -0
- matplotlibapi-4.0.0/tests/test_network.py +189 -0
- {matplotlibapi-3.2.21 → matplotlibapi-4.0.0}/tests/test_pie.py +2 -2
- {matplotlibapi-3.2.21 → matplotlibapi-4.0.0}/tests/test_pivot.py +2 -2
- {matplotlibapi-3.2.21 → matplotlibapi-4.0.0}/tests/test_sankey.py +1 -1
- {matplotlibapi-3.2.21 → matplotlibapi-4.0.0}/tests/test_smoke.py +9 -4
- matplotlibapi-4.0.0/tests/test_style_template.py +27 -0
- {matplotlibapi-3.2.21 → matplotlibapi-4.0.0}/tests/test_sunburst.py +1 -1
- {matplotlibapi-3.2.21 → matplotlibapi-4.0.0}/tests/test_table.py +1 -1
- {matplotlibapi-3.2.21 → matplotlibapi-4.0.0}/tests/test_timeseries.py +1 -1
- {matplotlibapi-3.2.21 → matplotlibapi-4.0.0}/tests/test_treemap.py +1 -1
- {matplotlibapi-3.2.21 → matplotlibapi-4.0.0}/tests/test_waffle.py +1 -1
- {matplotlibapi-3.2.21 → matplotlibapi-4.0.0}/tests/test_wordcloud.py +4 -4
- matplotlibapi-3.2.21/.github/workflows/ci.yml +0 -43
- matplotlibapi-3.2.21/MatplotLibAPI/Area.py +0 -80
- matplotlibapi-3.2.21/MatplotLibAPI/Bar.py +0 -83
- matplotlibapi-3.2.21/MatplotLibAPI/BoxViolin.py +0 -75
- matplotlibapi-3.2.21/MatplotLibAPI/Bubble.py +0 -458
- matplotlibapi-3.2.21/MatplotLibAPI/Heatmap.py +0 -121
- matplotlibapi-3.2.21/MatplotLibAPI/Histogram.py +0 -73
- matplotlibapi-3.2.21/MatplotLibAPI/Network.py +0 -989
- matplotlibapi-3.2.21/MatplotLibAPI/Pie.py +0 -70
- matplotlibapi-3.2.21/MatplotLibAPI/Pivot.py +0 -134
- matplotlibapi-3.2.21/MatplotLibAPI/Sankey.py +0 -46
- matplotlibapi-3.2.21/MatplotLibAPI/Sunburst.py +0 -89
- matplotlibapi-3.2.21/MatplotLibAPI/Waffle.py +0 -86
- matplotlibapi-3.2.21/MatplotLibAPI/Wordcloud.py +0 -373
- matplotlibapi-3.2.21/MatplotLibAPI/__init__.py +0 -89
- matplotlibapi-3.2.21/MatplotLibAPI/_typing.py +0 -17
- matplotlibapi-3.2.21/tests/test_network.py +0 -29
- {matplotlibapi-3.2.21 → matplotlibapi-4.0.0}/.gitignore +0 -0
- {matplotlibapi-3.2.21 → matplotlibapi-4.0.0}/LICENSE +0 -0
- {matplotlibapi-3.2.21 → matplotlibapi-4.0.0}/SECURITY.md +0 -0
- {matplotlibapi-3.2.21 → matplotlibapi-4.0.0}/SUGGESTIONS.md +0 -0
- /matplotlibapi-3.2.21/scripts/generate_sample_data.py → /matplotlibapi-4.0.0/examples/sample_data.py +0 -0
- {matplotlibapi-3.2.21 → matplotlibapi-4.0.0}/tests/__init__.py +0 -0
- {matplotlibapi-3.2.21 → matplotlibapi-4.0.0}/tests/test_dependencies.py +0 -0
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# To get started with Dependabot version updates, you'll need to specify which
|
|
2
|
+
# package ecosystems to update and where the package manifests are located.
|
|
3
|
+
# Please see the documentation for all configuration options:
|
|
4
|
+
# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
|
|
5
|
+
version: 2
|
|
6
|
+
updates:
|
|
7
|
+
- package-ecosystem: "pip"
|
|
8
|
+
directory: "/"
|
|
9
|
+
schedule:
|
|
10
|
+
interval: "weekly"
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
name: Python CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: read
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
build:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
strategy:
|
|
16
|
+
matrix:
|
|
17
|
+
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
|
|
18
|
+
|
|
19
|
+
steps:
|
|
20
|
+
- uses: actions/checkout@v4
|
|
21
|
+
|
|
22
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
23
|
+
uses: actions/setup-python@v4
|
|
24
|
+
with:
|
|
25
|
+
python-version: ${{ matrix.python-version }}
|
|
26
|
+
|
|
27
|
+
- name: Install dependencies
|
|
28
|
+
run: |
|
|
29
|
+
python -m pip install --upgrade pip
|
|
30
|
+
pip install -e .[dev]
|
|
31
|
+
|
|
32
|
+
- name: Run docstring style checks
|
|
33
|
+
run: pydocstyle src
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
- name: Set Black target version
|
|
37
|
+
id: black_version
|
|
38
|
+
run: echo "BLACK_TARGET_VERSION=py${PYTHON_VERSION//./}" >> $GITHUB_ENV
|
|
39
|
+
env:
|
|
40
|
+
PYTHON_VERSION: ${{ matrix.python-version }}
|
|
41
|
+
|
|
42
|
+
- name: Format check with black
|
|
43
|
+
run: black --check . --target-version=$BLACK_TARGET_VERSION
|
|
44
|
+
|
|
45
|
+
- name: Type check with pyright
|
|
46
|
+
run: pyright src
|
|
@@ -21,9 +21,9 @@ jobs:
|
|
|
21
21
|
runs-on: ubuntu-latest
|
|
22
22
|
|
|
23
23
|
steps:
|
|
24
|
-
- uses: actions/checkout@
|
|
24
|
+
- uses: actions/checkout@v4
|
|
25
25
|
- name: Set up Python
|
|
26
|
-
uses: actions/setup-python@
|
|
26
|
+
uses: actions/setup-python@v4
|
|
27
27
|
with:
|
|
28
28
|
python-version: '3.x'
|
|
29
29
|
- name: Install dependencies
|
|
@@ -33,7 +33,6 @@ jobs:
|
|
|
33
33
|
- name: Build package
|
|
34
34
|
run: python -m build
|
|
35
35
|
- name: Publish package
|
|
36
|
-
uses: pypa/gh-action-pypi-publish@
|
|
36
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
37
37
|
with:
|
|
38
|
-
user: __token__
|
|
39
38
|
password: ${{ secrets.PYPI_API_TOKEN }}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
repos:
|
|
2
|
+
- repo: https://github.com/psf/black
|
|
3
|
+
rev: 24.3.0
|
|
4
|
+
hooks:
|
|
5
|
+
- id: black
|
|
6
|
+
language_version: python3
|
|
7
|
+
|
|
8
|
+
- repo: https://github.com/PyCQA/pydocstyle
|
|
9
|
+
rev: 6.3.0
|
|
10
|
+
hooks:
|
|
11
|
+
- id: pydocstyle
|
|
12
|
+
name: pydocstyle
|
|
13
|
+
entry: pydocstyle
|
|
14
|
+
language: system
|
|
15
|
+
types: [python]
|
|
16
|
+
|
|
17
|
+
- repo: https://github.com/pre-commit/mirrors-pyright
|
|
18
|
+
rev: v1.1.350
|
|
19
|
+
hooks:
|
|
20
|
+
- id: pyright
|
|
21
|
+
name: pyright
|
|
22
|
+
entry: pyright
|
|
23
|
+
language: node
|
|
24
|
+
types: [python]
|
|
25
|
+
|
|
26
|
+
- repo: local
|
|
27
|
+
hooks:
|
|
28
|
+
- id: pytest
|
|
29
|
+
name: pytest
|
|
30
|
+
entry: pytest -q --cov=MatplotLibAPI --cov-report=term-missing --cov-fail-under=70
|
|
31
|
+
language: system
|
|
32
|
+
types: [python]
|
|
33
|
+
pass_filenames: false
|
|
@@ -60,7 +60,7 @@ pytest -q --cov=MatplotLibAPI --cov-report=term-missing --cov-fail-under=70
|
|
|
60
60
|
|
|
61
61
|
Each pull request should include:
|
|
62
62
|
|
|
63
|
-
1. **Summary** – brief description of the change.
|
|
63
|
+
1. **Summary** – brief description of the change. Mention breaking changes.
|
|
64
64
|
2. **Testing** – commands run and confirmation that the tests passed.
|
|
65
65
|
|
|
66
66
|
Example PR body:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: MatplotLibAPI
|
|
3
|
-
Version:
|
|
3
|
+
Version: 4.0.0
|
|
4
4
|
License-File: LICENSE
|
|
5
5
|
Requires-Python: >=3.8
|
|
6
6
|
Requires-Dist: kaleido
|
|
@@ -21,6 +21,8 @@ Requires-Dist: pytest; extra == 'dev'
|
|
|
21
21
|
Requires-Dist: pytest-cov; extra == 'dev'
|
|
22
22
|
Requires-Dist: pytest-pydocstyle; extra == 'dev'
|
|
23
23
|
Requires-Dist: tomli; extra == 'dev'
|
|
24
|
+
Provides-Extra: mcp
|
|
25
|
+
Requires-Dist: mcp>=1.0.0; extra == 'mcp'
|
|
24
26
|
Description-Content-Type: text/markdown
|
|
25
27
|
|
|
26
28
|
# MatplotLibAPI
|
|
@@ -47,23 +49,98 @@ This will create a `data` directory with CSV files for each plot type.
|
|
|
47
49
|
|
|
48
50
|
## Usage
|
|
49
51
|
|
|
50
|
-
Here's a simple example of how to create a bubble chart using
|
|
52
|
+
Here's a simple example of how to create a bubble chart using the object-based API with a sample CSV file:
|
|
51
53
|
|
|
52
54
|
```python
|
|
53
55
|
import pandas as pd
|
|
54
56
|
import matplotlib.pyplot as plt
|
|
55
|
-
from MatplotLibAPI import
|
|
57
|
+
from MatplotLibAPI.bubble import Bubble
|
|
56
58
|
|
|
57
59
|
# Load the sample data
|
|
58
60
|
df = pd.read_csv('data/bubble.csv')
|
|
59
61
|
|
|
60
|
-
#
|
|
61
|
-
fig =
|
|
62
|
+
# Build and render the bubble chart
|
|
63
|
+
fig = Bubble(
|
|
64
|
+
pd_df=df,
|
|
65
|
+
label='country',
|
|
66
|
+
x='gdp_per_capita',
|
|
67
|
+
y='population',
|
|
68
|
+
z='population',
|
|
69
|
+
).fplot(title='Country Statistics')
|
|
62
70
|
|
|
63
71
|
# Display the plot
|
|
64
72
|
plt.show()
|
|
65
73
|
```
|
|
66
74
|
|
|
75
|
+
|
|
76
|
+
## MCP Integration
|
|
77
|
+
|
|
78
|
+
You can run a dedicated MCP server that exposes MatplotLibAPI plotting tools for LLM agents.
|
|
79
|
+
|
|
80
|
+
1. Install MCP dependencies:
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
pip install -e .[mcp]
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
2. Start the MCP server over stdio:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
matplotlibapi-mcp
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Tool surface
|
|
93
|
+
|
|
94
|
+
The MCP server provides these tools:
|
|
95
|
+
|
|
96
|
+
- `plot_bubble`: dedicated bubble-chart rendering.
|
|
97
|
+
- `plot_network`: dedicated network-chart rendering.
|
|
98
|
+
- `plot_module`: generic module renderer for `bar`, `histogram`, `box_violin`, `heatmap`, `correlation_matrix`, `area`, `pie`, `waffle`, `sankey`, `table`, `timeserie`, `wordcloud`, `treemap`, and `sunburst`.
|
|
99
|
+
- Explicit module endpoints such as `plot_bar`, `plot_heatmap`, `plot_sankey`, `plot_treemap`, and others for direct LLM tool selection with no module-dispatch step.
|
|
100
|
+
- `describe_plot_modules`: discoverability endpoint that returns supported modules, shared input contract, parameter hints, and dedicated-tool mapping.
|
|
101
|
+
|
|
102
|
+
All rendering tools accept either:
|
|
103
|
+
|
|
104
|
+
- `csv_path`: filesystem path to a CSV file, or
|
|
105
|
+
- `table`: in-memory records (`list[dict]`).
|
|
106
|
+
|
|
107
|
+
All rendering tools return PNG bytes (octet payload) for downstream transport.
|
|
108
|
+
|
|
109
|
+
For LLM orchestration, explicit endpoints are generally easier to select and ground (for example `plot_heatmap` rather than `plot_module` + `plot_module="heatmap"`). Keep `plot_module` for dynamic clients that need one generic surface.
|
|
110
|
+
|
|
111
|
+
### Discoverability-first workflow
|
|
112
|
+
|
|
113
|
+
For dynamic clients and agent exploration, use this sequence:
|
|
114
|
+
|
|
115
|
+
1. Call `describe_plot_modules`.
|
|
116
|
+
2. Select a module from `supported_plot_modules`.
|
|
117
|
+
3. Read recommended keys from `parameter_hints[module_name]`.
|
|
118
|
+
4. Call `plot_module` with `params` + `csv_path` or `table`.
|
|
119
|
+
|
|
120
|
+
If a module key is invalid, `plot_module` returns a clear error with supported values.
|
|
121
|
+
|
|
122
|
+
### Example generic call
|
|
123
|
+
|
|
124
|
+
Example payload for `plot_module` with in-memory table records:
|
|
125
|
+
|
|
126
|
+
```json
|
|
127
|
+
{
|
|
128
|
+
"plot_module": "heatmap",
|
|
129
|
+
"table": [
|
|
130
|
+
{"month": "Jan", "channel": "Email", "engagements": 120},
|
|
131
|
+
{"month": "Jan", "channel": "Social", "engagements": 200}
|
|
132
|
+
],
|
|
133
|
+
"params": {
|
|
134
|
+
"x": "month",
|
|
135
|
+
"y": "channel",
|
|
136
|
+
"value": "engagements",
|
|
137
|
+
"title": "Engagement Heatmap"
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
The package exposes a single MCP entry point: `matplotlibapi-mcp`.
|
|
143
|
+
|
|
67
144
|
## Plot Types
|
|
68
145
|
|
|
69
146
|
The library supports the following plot types:
|
|
@@ -92,10 +169,16 @@ This repository includes a `data` directory with sample CSV files for each plot
|
|
|
92
169
|
|
|
93
170
|
```python
|
|
94
171
|
import pandas as pd
|
|
95
|
-
from MatplotLibAPI import
|
|
172
|
+
from MatplotLibAPI.bubble import Bubble
|
|
96
173
|
|
|
97
174
|
df = pd.read_csv('data/bubble.csv')
|
|
98
|
-
fig =
|
|
175
|
+
fig = Bubble(
|
|
176
|
+
pd_df=df,
|
|
177
|
+
label='country',
|
|
178
|
+
x='gdp_per_capita',
|
|
179
|
+
y='life_expectancy',
|
|
180
|
+
z='population',
|
|
181
|
+
).fplot()
|
|
99
182
|
fig.show()
|
|
100
183
|
```
|
|
101
184
|
|
|
@@ -103,10 +186,16 @@ fig.show()
|
|
|
103
186
|
|
|
104
187
|
```python
|
|
105
188
|
import pandas as pd
|
|
106
|
-
from MatplotLibAPI import
|
|
189
|
+
from MatplotLibAPI.network import NetworkGraph
|
|
107
190
|
|
|
108
191
|
df = pd.read_csv('data/network.csv')
|
|
109
|
-
|
|
192
|
+
graph = NetworkGraph.from_pandas_edgelist(
|
|
193
|
+
df,
|
|
194
|
+
source='city_a',
|
|
195
|
+
target='city_b',
|
|
196
|
+
edge_weight_col='distance_km',
|
|
197
|
+
)
|
|
198
|
+
fig = graph.fplot(title='City Network', edge_weight_col='distance_km')
|
|
110
199
|
fig.show()
|
|
111
200
|
```
|
|
112
201
|
|
|
@@ -22,23 +22,98 @@ This will create a `data` directory with CSV files for each plot type.
|
|
|
22
22
|
|
|
23
23
|
## Usage
|
|
24
24
|
|
|
25
|
-
Here's a simple example of how to create a bubble chart using
|
|
25
|
+
Here's a simple example of how to create a bubble chart using the object-based API with a sample CSV file:
|
|
26
26
|
|
|
27
27
|
```python
|
|
28
28
|
import pandas as pd
|
|
29
29
|
import matplotlib.pyplot as plt
|
|
30
|
-
from MatplotLibAPI import
|
|
30
|
+
from MatplotLibAPI.bubble import Bubble
|
|
31
31
|
|
|
32
32
|
# Load the sample data
|
|
33
33
|
df = pd.read_csv('data/bubble.csv')
|
|
34
34
|
|
|
35
|
-
#
|
|
36
|
-
fig =
|
|
35
|
+
# Build and render the bubble chart
|
|
36
|
+
fig = Bubble(
|
|
37
|
+
pd_df=df,
|
|
38
|
+
label='country',
|
|
39
|
+
x='gdp_per_capita',
|
|
40
|
+
y='population',
|
|
41
|
+
z='population',
|
|
42
|
+
).fplot(title='Country Statistics')
|
|
37
43
|
|
|
38
44
|
# Display the plot
|
|
39
45
|
plt.show()
|
|
40
46
|
```
|
|
41
47
|
|
|
48
|
+
|
|
49
|
+
## MCP Integration
|
|
50
|
+
|
|
51
|
+
You can run a dedicated MCP server that exposes MatplotLibAPI plotting tools for LLM agents.
|
|
52
|
+
|
|
53
|
+
1. Install MCP dependencies:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
pip install -e .[mcp]
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
2. Start the MCP server over stdio:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
matplotlibapi-mcp
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Tool surface
|
|
66
|
+
|
|
67
|
+
The MCP server provides these tools:
|
|
68
|
+
|
|
69
|
+
- `plot_bubble`: dedicated bubble-chart rendering.
|
|
70
|
+
- `plot_network`: dedicated network-chart rendering.
|
|
71
|
+
- `plot_module`: generic module renderer for `bar`, `histogram`, `box_violin`, `heatmap`, `correlation_matrix`, `area`, `pie`, `waffle`, `sankey`, `table`, `timeserie`, `wordcloud`, `treemap`, and `sunburst`.
|
|
72
|
+
- Explicit module endpoints such as `plot_bar`, `plot_heatmap`, `plot_sankey`, `plot_treemap`, and others for direct LLM tool selection with no module-dispatch step.
|
|
73
|
+
- `describe_plot_modules`: discoverability endpoint that returns supported modules, shared input contract, parameter hints, and dedicated-tool mapping.
|
|
74
|
+
|
|
75
|
+
All rendering tools accept either:
|
|
76
|
+
|
|
77
|
+
- `csv_path`: filesystem path to a CSV file, or
|
|
78
|
+
- `table`: in-memory records (`list[dict]`).
|
|
79
|
+
|
|
80
|
+
All rendering tools return PNG bytes (octet payload) for downstream transport.
|
|
81
|
+
|
|
82
|
+
For LLM orchestration, explicit endpoints are generally easier to select and ground (for example `plot_heatmap` rather than `plot_module` + `plot_module="heatmap"`). Keep `plot_module` for dynamic clients that need one generic surface.
|
|
83
|
+
|
|
84
|
+
### Discoverability-first workflow
|
|
85
|
+
|
|
86
|
+
For dynamic clients and agent exploration, use this sequence:
|
|
87
|
+
|
|
88
|
+
1. Call `describe_plot_modules`.
|
|
89
|
+
2. Select a module from `supported_plot_modules`.
|
|
90
|
+
3. Read recommended keys from `parameter_hints[module_name]`.
|
|
91
|
+
4. Call `plot_module` with `params` + `csv_path` or `table`.
|
|
92
|
+
|
|
93
|
+
If a module key is invalid, `plot_module` returns a clear error with supported values.
|
|
94
|
+
|
|
95
|
+
### Example generic call
|
|
96
|
+
|
|
97
|
+
Example payload for `plot_module` with in-memory table records:
|
|
98
|
+
|
|
99
|
+
```json
|
|
100
|
+
{
|
|
101
|
+
"plot_module": "heatmap",
|
|
102
|
+
"table": [
|
|
103
|
+
{"month": "Jan", "channel": "Email", "engagements": 120},
|
|
104
|
+
{"month": "Jan", "channel": "Social", "engagements": 200}
|
|
105
|
+
],
|
|
106
|
+
"params": {
|
|
107
|
+
"x": "month",
|
|
108
|
+
"y": "channel",
|
|
109
|
+
"value": "engagements",
|
|
110
|
+
"title": "Engagement Heatmap"
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
The package exposes a single MCP entry point: `matplotlibapi-mcp`.
|
|
116
|
+
|
|
42
117
|
## Plot Types
|
|
43
118
|
|
|
44
119
|
The library supports the following plot types:
|
|
@@ -67,10 +142,16 @@ This repository includes a `data` directory with sample CSV files for each plot
|
|
|
67
142
|
|
|
68
143
|
```python
|
|
69
144
|
import pandas as pd
|
|
70
|
-
from MatplotLibAPI import
|
|
145
|
+
from MatplotLibAPI.bubble import Bubble
|
|
71
146
|
|
|
72
147
|
df = pd.read_csv('data/bubble.csv')
|
|
73
|
-
fig =
|
|
148
|
+
fig = Bubble(
|
|
149
|
+
pd_df=df,
|
|
150
|
+
label='country',
|
|
151
|
+
x='gdp_per_capita',
|
|
152
|
+
y='life_expectancy',
|
|
153
|
+
z='population',
|
|
154
|
+
).fplot()
|
|
74
155
|
fig.show()
|
|
75
156
|
```
|
|
76
157
|
|
|
@@ -78,10 +159,16 @@ fig.show()
|
|
|
78
159
|
|
|
79
160
|
```python
|
|
80
161
|
import pandas as pd
|
|
81
|
-
from MatplotLibAPI import
|
|
162
|
+
from MatplotLibAPI.network import NetworkGraph
|
|
82
163
|
|
|
83
164
|
df = pd.read_csv('data/network.csv')
|
|
84
|
-
|
|
165
|
+
graph = NetworkGraph.from_pandas_edgelist(
|
|
166
|
+
df,
|
|
167
|
+
source='city_a',
|
|
168
|
+
target='city_b',
|
|
169
|
+
edge_weight_col='distance_km',
|
|
170
|
+
)
|
|
171
|
+
fig = graph.fplot(title='City Network', edge_weight_col='distance_km')
|
|
85
172
|
fig.show()
|
|
86
173
|
```
|
|
87
174
|
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"""Global example fixtures and configuration."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import sys
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
# Ensure the src directory is on the Python path for src layout
|
|
9
|
+
sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "src"))
|
|
Binary file
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Example module for network graph sample data generation and plotting.
|
|
3
|
+
|
|
4
|
+
This module provides functions to generate and plot sample network data for testing.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import sys
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
from matplotlib.figure import Figure
|
|
10
|
+
import pandas as pd
|
|
11
|
+
|
|
12
|
+
sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "src"))
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def generate_sample_network_data() -> pd.DataFrame:
|
|
16
|
+
"""Generate and save sample data for a network graph."""
|
|
17
|
+
data = {
|
|
18
|
+
"city_a": ["New York", "London", "Tokyo", "Sydney", "New York"],
|
|
19
|
+
"city_b": ["London", "Tokyo", "Sydney", "New York", "Tokyo"],
|
|
20
|
+
"distance_km": [5585, 9562, 7824, 16027, 10850],
|
|
21
|
+
}
|
|
22
|
+
df = pd.DataFrame(data)
|
|
23
|
+
return df
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def plot_sample_network_data() -> Figure:
|
|
27
|
+
"""Load a sample DataFrame for testing."""
|
|
28
|
+
from MatplotLibAPI.network import NetworkGraph
|
|
29
|
+
|
|
30
|
+
pd_df = generate_sample_network_data()
|
|
31
|
+
graph = NetworkGraph.from_pandas_edgelist(
|
|
32
|
+
pd_df, source="city_a", target="city_b", edge_weight_col="distance_km"
|
|
33
|
+
)
|
|
34
|
+
plot_fig = graph.fplot(title="Network Graph")
|
|
35
|
+
|
|
36
|
+
return plot_fig
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
if __name__ == "__main__":
|
|
40
|
+
plot_fig = plot_sample_network_data()
|
|
41
|
+
plot_fig.show()
|
|
@@ -3,7 +3,7 @@ requires = ["hatchling"]
|
|
|
3
3
|
build-backend = "hatchling.build"
|
|
4
4
|
[project]
|
|
5
5
|
name = "MatplotLibAPI"
|
|
6
|
-
version = "
|
|
6
|
+
version = "4.0.0"
|
|
7
7
|
readme = "README.md"
|
|
8
8
|
requires-python = ">=3.8"
|
|
9
9
|
dependencies = [
|
|
@@ -29,6 +29,21 @@ dev = [
|
|
|
29
29
|
"pytest-cov",
|
|
30
30
|
"tomli",
|
|
31
31
|
]
|
|
32
|
+
mcp = [
|
|
33
|
+
"mcp>=1.0.0",
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
[project.scripts]
|
|
37
|
+
matplotlibapi-mcp = "MatplotLibAPI.mcp_server:main"
|
|
38
|
+
|
|
32
39
|
|
|
33
40
|
[tool.hatch.build.targets.wheel]
|
|
34
|
-
packages = ["MatplotLibAPI"]
|
|
41
|
+
packages = ["src/MatplotLibAPI"]
|
|
42
|
+
|
|
43
|
+
[tool.pyright]
|
|
44
|
+
extraPaths = ["src"]
|
|
45
|
+
|
|
46
|
+
[tool.pydocstyle]
|
|
47
|
+
convention = "numpy"
|
|
48
|
+
|
|
49
|
+
[tool.pytest.ini_options]
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# Script to run all CI checks locally before committing
|
|
4
|
+
# This ensures your changes will pass the automated checks in the CI pipeline
|
|
5
|
+
|
|
6
|
+
set -e # Exit on first error
|
|
7
|
+
|
|
8
|
+
echo "=========================================="
|
|
9
|
+
echo "Running CI Checks"
|
|
10
|
+
echo "=========================================="
|
|
11
|
+
echo ""
|
|
12
|
+
|
|
13
|
+
# Change to project root directory
|
|
14
|
+
cd "$(git rev-parse --show-toplevel)"
|
|
15
|
+
|
|
16
|
+
# Track overall status
|
|
17
|
+
FAILED=0
|
|
18
|
+
|
|
19
|
+
pip install --upgrade pip
|
|
20
|
+
pip install --upgrade -e ".[dev]"
|
|
21
|
+
|
|
22
|
+
# Style Checks
|
|
23
|
+
echo "▶ Running pydocstyle..."
|
|
24
|
+
if pydocstyle src; then
|
|
25
|
+
echo "✓ pydocstyle passed"
|
|
26
|
+
else
|
|
27
|
+
echo "✗ pydocstyle failed"
|
|
28
|
+
FAILED=1
|
|
29
|
+
fi
|
|
30
|
+
echo ""
|
|
31
|
+
|
|
32
|
+
echo "▶ Running black..."
|
|
33
|
+
if black .; then
|
|
34
|
+
echo "✓ black passed"
|
|
35
|
+
else
|
|
36
|
+
echo "✗ black failed"
|
|
37
|
+
FAILED=1
|
|
38
|
+
fi
|
|
39
|
+
echo ""
|
|
40
|
+
|
|
41
|
+
# Static Type Analysis
|
|
42
|
+
echo "▶ Running pyright..."
|
|
43
|
+
if pyright src; then
|
|
44
|
+
echo "✓ pyright passed"
|
|
45
|
+
else
|
|
46
|
+
echo "✗ pyright failed"
|
|
47
|
+
FAILED=1
|
|
48
|
+
fi
|
|
49
|
+
echo ""
|
|
50
|
+
|
|
51
|
+
# Unit Tests and Coverage
|
|
52
|
+
echo "▶ Running pytest with coverage..."
|
|
53
|
+
if pytest -q --cov=src --cov-report=term-missing --cov-fail-under=70; then
|
|
54
|
+
echo "✓ pytest passed"
|
|
55
|
+
else
|
|
56
|
+
echo "✗ pytest failed"
|
|
57
|
+
FAILED=1
|
|
58
|
+
fi
|
|
59
|
+
echo ""
|
|
60
|
+
|
|
61
|
+
# Summary
|
|
62
|
+
echo "=========================================="
|
|
63
|
+
if [ $FAILED -eq 0 ]; then
|
|
64
|
+
echo "✓ All CI checks passed!"
|
|
65
|
+
echo "=========================================="
|
|
66
|
+
exit 0
|
|
67
|
+
else
|
|
68
|
+
echo "✗ Some CI checks failed"
|
|
69
|
+
echo "=========================================="
|
|
70
|
+
exit 1
|
|
71
|
+
fi
|