rustplotlib 1.0.0__tar.gz → 2.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.
- {rustplotlib-1.0.0 → rustplotlib-2.0.0}/Cargo.lock +1 -1
- {rustplotlib-1.0.0 → rustplotlib-2.0.0}/Cargo.toml +1 -1
- rustplotlib-2.0.0/PKG-INFO +404 -0
- rustplotlib-2.0.0/README.md +383 -0
- rustplotlib-2.0.0/ROADMAP.md +171 -0
- {rustplotlib-1.0.0 → rustplotlib-2.0.0}/pyproject.toml +1 -1
- {rustplotlib-1.0.0 → rustplotlib-2.0.0}/python/rustplotlib/__init__.py +11 -0
- rustplotlib-2.0.0/python/rustplotlib/axes/__init__.py +10 -0
- rustplotlib-2.0.0/python/rustplotlib/backends/backend_inline.py +24 -0
- rustplotlib-2.0.0/python/rustplotlib/cm.py +56 -0
- rustplotlib-2.0.0/python/rustplotlib/collections.py +70 -0
- rustplotlib-2.0.0/python/rustplotlib/figure.py +10 -0
- rustplotlib-2.0.0/python/rustplotlib/lines.py +47 -0
- rustplotlib-2.0.0/python/rustplotlib/patheffects.py +36 -0
- {rustplotlib-1.0.0 → rustplotlib-2.0.0}/python/rustplotlib/pyplot.py +532 -25
- rustplotlib-2.0.0/python/rustplotlib/spines.py +22 -0
- rustplotlib-2.0.0/python/rustplotlib/text.py +30 -0
- rustplotlib-2.0.0/python/rustplotlib/transforms.py +68 -0
- {rustplotlib-1.0.0 → rustplotlib-2.0.0}/src/artists/bar.rs +48 -0
- rustplotlib-2.0.0/src/artists/broken_barh.rs +135 -0
- rustplotlib-2.0.0/src/artists/contour3d.rs +264 -0
- rustplotlib-2.0.0/src/artists/eventplot.rs +137 -0
- {rustplotlib-1.0.0 → rustplotlib-2.0.0}/src/artists/fill_between.rs +28 -0
- {rustplotlib-1.0.0 → rustplotlib-2.0.0}/src/artists/hist.rs +5 -0
- rustplotlib-2.0.0/src/artists/image.rs +656 -0
- {rustplotlib-1.0.0 → rustplotlib-2.0.0}/src/artists/legend.rs +18 -5
- {rustplotlib-1.0.0 → rustplotlib-2.0.0}/src/artists/line2d.rs +122 -0
- {rustplotlib-1.0.0 → rustplotlib-2.0.0}/src/artists/mod.rs +10 -0
- rustplotlib-2.0.0/src/artists/radar.rs +228 -0
- {rustplotlib-1.0.0 → rustplotlib-2.0.0}/src/artists/scatter.rs +23 -0
- rustplotlib-2.0.0/src/artists/trisurf3d.rs +235 -0
- {rustplotlib-1.0.0 → rustplotlib-2.0.0}/src/axes.rs +636 -15
- {rustplotlib-1.0.0 → rustplotlib-2.0.0}/src/figure.rs +661 -20
- rustplotlib-2.0.0/src/lib.rs +47 -0
- rustplotlib-2.0.0/src/svg_renderer.rs +241 -0
- {rustplotlib-1.0.0 → rustplotlib-2.0.0}/src/text.rs +71 -23
- {rustplotlib-1.0.0 → rustplotlib-2.0.0}/tests/test_figure.py +4 -1
- rustplotlib-2.0.0/tests/test_new_features.py +254 -0
- {rustplotlib-1.0.0 → rustplotlib-2.0.0}/tests/test_phase8.py +13 -5
- rustplotlib-1.0.0/PKG-INFO +0 -292
- rustplotlib-1.0.0/README.md +0 -271
- rustplotlib-1.0.0/ROADMAP.md +0 -201
- rustplotlib-1.0.0/python/rustplotlib/backends/backend_inline.py +0 -4
- rustplotlib-1.0.0/src/artists/image.rs +0 -430
- rustplotlib-1.0.0/src/lib.rs +0 -23
- {rustplotlib-1.0.0 → rustplotlib-2.0.0}/.github/workflows/ci.yml +0 -0
- {rustplotlib-1.0.0 → rustplotlib-2.0.0}/.gitignore +0 -0
- {rustplotlib-1.0.0 → rustplotlib-2.0.0}/LICENSE +0 -0
- {rustplotlib-1.0.0 → rustplotlib-2.0.0}/dados/Data/PerfisTemp_rustplotlib.py +0 -0
- {rustplotlib-1.0.0 → rustplotlib-2.0.0}/python/rustplotlib/animation.py +0 -0
- {rustplotlib-1.0.0 → rustplotlib-2.0.0}/python/rustplotlib/backends/__init__.py +0 -0
- {rustplotlib-1.0.0 → rustplotlib-2.0.0}/python/rustplotlib/backends/backend_pdf.py +0 -0
- {rustplotlib-1.0.0 → rustplotlib-2.0.0}/python/rustplotlib/colors.py +0 -0
- {rustplotlib-1.0.0 → rustplotlib-2.0.0}/python/rustplotlib/cycler.py +0 -0
- {rustplotlib-1.0.0 → rustplotlib-2.0.0}/python/rustplotlib/dates.py +0 -0
- {rustplotlib-1.0.0 → rustplotlib-2.0.0}/python/rustplotlib/font_manager.py +0 -0
- {rustplotlib-1.0.0 → rustplotlib-2.0.0}/python/rustplotlib/gridspec.py +0 -0
- {rustplotlib-1.0.0 → rustplotlib-2.0.0}/python/rustplotlib/mpl_toolkits/__init__.py +0 -0
- {rustplotlib-1.0.0 → rustplotlib-2.0.0}/python/rustplotlib/mpl_toolkits/mplot3d/__init__.py +0 -0
- {rustplotlib-1.0.0 → rustplotlib-2.0.0}/python/rustplotlib/patches.py +0 -0
- {rustplotlib-1.0.0 → rustplotlib-2.0.0}/python/rustplotlib/pyplot.pyi +0 -0
- {rustplotlib-1.0.0 → rustplotlib-2.0.0}/python/rustplotlib/style/__init__.py +0 -0
- {rustplotlib-1.0.0 → rustplotlib-2.0.0}/python/rustplotlib/ticker.py +0 -0
- {rustplotlib-1.0.0 → rustplotlib-2.0.0}/python/rustplotlib/widgets.py +0 -0
- {rustplotlib-1.0.0 → rustplotlib-2.0.0}/src/artists/bar3d.rs +0 -0
- {rustplotlib-1.0.0 → rustplotlib-2.0.0}/src/artists/barh.rs +0 -0
- {rustplotlib-1.0.0 → rustplotlib-2.0.0}/src/artists/boxplot.rs +0 -0
- {rustplotlib-1.0.0 → rustplotlib-2.0.0}/src/artists/contour.rs +0 -0
- {rustplotlib-1.0.0 → rustplotlib-2.0.0}/src/artists/errorbar.rs +0 -0
- {rustplotlib-1.0.0 → rustplotlib-2.0.0}/src/artists/fill_betweenx.rs +0 -0
- {rustplotlib-1.0.0 → rustplotlib-2.0.0}/src/artists/hexbin.rs +0 -0
- {rustplotlib-1.0.0 → rustplotlib-2.0.0}/src/artists/line3d.rs +0 -0
- {rustplotlib-1.0.0 → rustplotlib-2.0.0}/src/artists/patches.rs +0 -0
- {rustplotlib-1.0.0 → rustplotlib-2.0.0}/src/artists/pie.rs +0 -0
- {rustplotlib-1.0.0 → rustplotlib-2.0.0}/src/artists/quiver.rs +0 -0
- {rustplotlib-1.0.0 → rustplotlib-2.0.0}/src/artists/scatter3d.rs +0 -0
- {rustplotlib-1.0.0 → rustplotlib-2.0.0}/src/artists/stem.rs +0 -0
- {rustplotlib-1.0.0 → rustplotlib-2.0.0}/src/artists/step.rs +0 -0
- {rustplotlib-1.0.0 → rustplotlib-2.0.0}/src/artists/streamplot.rs +0 -0
- {rustplotlib-1.0.0 → rustplotlib-2.0.0}/src/artists/surface3d.rs +0 -0
- {rustplotlib-1.0.0 → rustplotlib-2.0.0}/src/artists/violin.rs +0 -0
- {rustplotlib-1.0.0 → rustplotlib-2.0.0}/src/artists/wireframe3d.rs +0 -0
- {rustplotlib-1.0.0 → rustplotlib-2.0.0}/src/axes3d.rs +0 -0
- {rustplotlib-1.0.0 → rustplotlib-2.0.0}/src/colors.rs +0 -0
- {rustplotlib-1.0.0 → rustplotlib-2.0.0}/src/fonts/DejaVuSans.ttf +0 -0
- {rustplotlib-1.0.0 → rustplotlib-2.0.0}/src/projection3d.rs +0 -0
- {rustplotlib-1.0.0 → rustplotlib-2.0.0}/src/ticker.rs +0 -0
- {rustplotlib-1.0.0 → rustplotlib-2.0.0}/src/transforms.rs +0 -0
- {rustplotlib-1.0.0 → rustplotlib-2.0.0}/src/window.rs +0 -0
- {rustplotlib-1.0.0 → rustplotlib-2.0.0}/tests/test_3d.py +0 -0
- {rustplotlib-1.0.0 → rustplotlib-2.0.0}/tests/test_benchmark.py +0 -0
- {rustplotlib-1.0.0 → rustplotlib-2.0.0}/tests/test_colors.py +0 -0
- {rustplotlib-1.0.0 → rustplotlib-2.0.0}/tests/test_phase6_7.py +0 -0
- {rustplotlib-1.0.0 → rustplotlib-2.0.0}/tests/test_pyplot.py +0 -0
- {rustplotlib-1.0.0 → rustplotlib-2.0.0}/tests/test_ticker.py +0 -0
- {rustplotlib-1.0.0 → rustplotlib-2.0.0}/tests/test_transforms.py +0 -0
|
@@ -0,0 +1,404 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: rustplotlib
|
|
3
|
+
Version: 2.0.0
|
|
4
|
+
Classifier: Development Status :: 3 - Alpha
|
|
5
|
+
Classifier: Intended Audience :: Science/Research
|
|
6
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
7
|
+
Classifier: Programming Language :: Rust
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: Topic :: Scientific/Engineering :: Visualization
|
|
10
|
+
Requires-Dist: numpy
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Summary: Matplotlib drop-in replacement powered by Rust
|
|
13
|
+
Keywords: matplotlib,plotting,visualization,rust,performance
|
|
14
|
+
License: MIT
|
|
15
|
+
Requires-Python: >=3.9
|
|
16
|
+
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
|
|
17
|
+
Project-URL: Homepage, https://github.com/Thi4gon/rustplotlib
|
|
18
|
+
Project-URL: Issues, https://github.com/Thi4gon/rustplotlib/issues
|
|
19
|
+
Project-URL: Repository, https://github.com/Thi4gon/rustplotlib
|
|
20
|
+
|
|
21
|
+
# RustPlotLib
|
|
22
|
+
|
|
23
|
+
**Matplotlib reimplemented in Rust.** A high-performance drop-in replacement for Python's matplotlib, built from scratch with a native Rust rendering engine.
|
|
24
|
+
|
|
25
|
+
No Python runtime dependency for rendering. No wrappers. No subprocess calls. Pure Rust rasterization exposed to Python via [PyO3](https://pyo3.rs/).
|
|
26
|
+
|
|
27
|
+
[](https://github.com/Thi4gon/rustplotlib/actions)
|
|
28
|
+
[](https://pypi.org/project/rustplotlib/)
|
|
29
|
+
[](LICENSE)
|
|
30
|
+
[](https://pypi.org/project/rustplotlib/)
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## Why RustPlotLib?
|
|
35
|
+
|
|
36
|
+
| | matplotlib | Other Rust plotting libs | **rustplotlib** |
|
|
37
|
+
|---|---|---|---|
|
|
38
|
+
| Rendering engine | C/C++ (AGG) | None (wrap matplotlib or call Python) | **Rust native (tiny-skia)** |
|
|
39
|
+
| External dependencies | NumPy, Pillow, FreeType, etc. | Python + matplotlib required | **Zero** — self-contained |
|
|
40
|
+
| Performance | Baseline | Same or slower (subprocess overhead) | **Up to 30x faster** |
|
|
41
|
+
| Python API | Original | Rust-only or generates .py scripts | **Drop-in replacement** — same API |
|
|
42
|
+
| Approach | Interpreted + C extensions | Wrappers / code generators | **Full reimplementation in Rust** |
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## Installation
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
pip install rustplotlib
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Supports Python 3.9-3.13 on macOS, Linux, and Windows (pre-built wheels available).
|
|
53
|
+
|
|
54
|
+
Or build from source (requires Rust 1.70+ and Python 3.9+):
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
git clone https://github.com/Thi4gon/rustplotlib.git
|
|
58
|
+
cd rustplotlib
|
|
59
|
+
pip install maturin
|
|
60
|
+
maturin develop --release
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Usage
|
|
66
|
+
|
|
67
|
+
Just swap your import — everything else stays the same:
|
|
68
|
+
|
|
69
|
+
```python
|
|
70
|
+
# Before:
|
|
71
|
+
# import matplotlib.pyplot as plt
|
|
72
|
+
|
|
73
|
+
# After:
|
|
74
|
+
import rustplotlib.pyplot as plt
|
|
75
|
+
|
|
76
|
+
plt.plot([1, 2, 3, 4], [1, 4, 2, 3], label="data")
|
|
77
|
+
plt.title("My Plot")
|
|
78
|
+
plt.xlabel("X")
|
|
79
|
+
plt.ylabel("Y")
|
|
80
|
+
plt.legend()
|
|
81
|
+
plt.grid(True)
|
|
82
|
+
plt.savefig("plot.png")
|
|
83
|
+
plt.show()
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## What's Implemented
|
|
89
|
+
|
|
90
|
+
### 2D Plot Types (17 types)
|
|
91
|
+
| Function | Description |
|
|
92
|
+
|---|---|
|
|
93
|
+
| `plot()` | Line plots with color, linestyle, linewidth, markers, markevery, labels, alpha |
|
|
94
|
+
| `scatter()` | Scatter plots with per-point sizes, colors, markers, alpha |
|
|
95
|
+
| `bar()` / `barh()` | Vertical and horizontal bar charts (stacked via `bottom` param) |
|
|
96
|
+
| `hist()` | Histograms with configurable bins |
|
|
97
|
+
| `imshow()` | Image/heatmap display with 35+ colormaps |
|
|
98
|
+
| `fill_between()` / `fill_betweenx()` | Filled area between curves (vertical and horizontal) |
|
|
99
|
+
| `errorbar()` | Error bars with caps (xerr/yerr) |
|
|
100
|
+
| `step()` | Step plots (pre/post/mid) |
|
|
101
|
+
| `pie()` | Pie charts with labels |
|
|
102
|
+
| `boxplot()` | Box-and-whisker plots (Q1/median/Q3, whiskers, outliers) |
|
|
103
|
+
| `violinplot()` | Violin plots with Gaussian KDE |
|
|
104
|
+
| `stem()` | Stem plots with baseline |
|
|
105
|
+
| `contour()` / `contourf()` | Contour lines and filled contours (marching squares) |
|
|
106
|
+
| `hexbin()` | Hexagonal binning for 2D histograms |
|
|
107
|
+
| `quiver()` | Vector field arrows |
|
|
108
|
+
| `streamplot()` | Streamlines for vector fields (Euler integration) |
|
|
109
|
+
|
|
110
|
+
### 3D Plot Types (5 types)
|
|
111
|
+
| Function | Description |
|
|
112
|
+
|---|---|
|
|
113
|
+
| `plot()` (3D) | 3D line plots |
|
|
114
|
+
| `scatter()` (3D) | 3D scatter with depth sorting |
|
|
115
|
+
| `plot_surface()` | 3D surface plots with colormaps |
|
|
116
|
+
| `plot_wireframe()` | 3D wireframe plots |
|
|
117
|
+
| `bar3d()` | 3D bar charts with shading |
|
|
118
|
+
|
|
119
|
+
### Layout & Figure
|
|
120
|
+
| Function | Description |
|
|
121
|
+
|---|---|
|
|
122
|
+
| `subplots(nrows, ncols)` | Grid of axes with figsize/dpi |
|
|
123
|
+
| `subplot(nrows, ncols, index)` | Add single subplot |
|
|
124
|
+
| `subplot_mosaic()` | Named subplot layouts from ASCII art |
|
|
125
|
+
| `figure(figsize, dpi)` | Create new figure |
|
|
126
|
+
| `suptitle()` | Figure-level super title |
|
|
127
|
+
| `subplots_adjust()` | Control hspace/wspace between subplots |
|
|
128
|
+
| `tight_layout()` | Auto-adjust spacing |
|
|
129
|
+
| `add_subplot(projection='3d')` | Add 3D subplot |
|
|
130
|
+
| `clf()` / `cla()` / `close()` | Clear and close figures |
|
|
131
|
+
| `gcf()` / `gca()` | Get current figure/axes |
|
|
132
|
+
|
|
133
|
+
### Axes Customization
|
|
134
|
+
| Function | Description |
|
|
135
|
+
|---|---|
|
|
136
|
+
| `title()` / `set_title()` | Plot title with fontsize |
|
|
137
|
+
| `xlabel()` / `ylabel()` | Axis labels with fontsize |
|
|
138
|
+
| `set_xlim()` / `set_ylim()` | Axis range limits |
|
|
139
|
+
| `set_xscale('log')` / `set_yscale('log')` | Logarithmic scale |
|
|
140
|
+
| `set_xticks()` / `set_yticks()` | Custom tick positions |
|
|
141
|
+
| `set_xticklabels()` / `set_yticklabels()` | Custom tick labels |
|
|
142
|
+
| `tick_params()` | Tick direction, length, width, labelsize |
|
|
143
|
+
| `set_aspect('equal')` | Equal aspect ratio |
|
|
144
|
+
| `invert_xaxis()` / `invert_yaxis()` | Invert axis direction |
|
|
145
|
+
| `axis('off')` | Hide axes completely |
|
|
146
|
+
| `set_facecolor()` | Axes background color |
|
|
147
|
+
| `spines['right'].set_visible(False)` | Spine customization |
|
|
148
|
+
| `twinx()` | Secondary y-axis |
|
|
149
|
+
| `legend()` | Legend with line+marker swatches and positioning |
|
|
150
|
+
| `grid()` | Grid lines with color, linewidth, linestyle, alpha, which |
|
|
151
|
+
| `text()` | Positioned text annotations |
|
|
152
|
+
| `annotate()` | Text with arrow pointing to data |
|
|
153
|
+
| `table()` | Data table inside axes |
|
|
154
|
+
| `axhline()` / `axvline()` | Horizontal/vertical reference lines |
|
|
155
|
+
| `axhspan()` / `axvspan()` | Shaded horizontal/vertical regions |
|
|
156
|
+
| `hlines()` / `vlines()` | Multiple reference lines with bounds |
|
|
157
|
+
| `colorbar()` | Color scale bar for imshow/contour |
|
|
158
|
+
|
|
159
|
+
### Output Formats
|
|
160
|
+
| Method | Description |
|
|
161
|
+
|---|---|
|
|
162
|
+
| `savefig("file.png")` | Raster PNG (with dpi, transparent options) |
|
|
163
|
+
| `savefig("file.svg")` | Native vector SVG (real `<line>`, `<text>`, `<rect>` elements) |
|
|
164
|
+
| `savefig("file.pdf")` | PDF output |
|
|
165
|
+
| `show()` | Interactive window display |
|
|
166
|
+
| `PdfPages` | Multi-page PDF export |
|
|
167
|
+
|
|
168
|
+
### Animation
|
|
169
|
+
| Feature | Description |
|
|
170
|
+
|---|---|
|
|
171
|
+
| `FuncAnimation` | Function-based animation with frame generation |
|
|
172
|
+
| GIF export | Save animations as GIF (via Pillow) |
|
|
173
|
+
| PNG sequence | Save animation frames as individual PNGs |
|
|
174
|
+
|
|
175
|
+
### Styles & Themes
|
|
176
|
+
| Feature | Description |
|
|
177
|
+
|---|---|
|
|
178
|
+
| `style.use('dark_background')` | 6 built-in themes (default, dark_background, ggplot, seaborn, bmh, fivethirtyeight) |
|
|
179
|
+
| `rcParams` | Functional global configuration (30+ supported keys) |
|
|
180
|
+
| `set_facecolor()` | Figure and axes background colors |
|
|
181
|
+
|
|
182
|
+
### Colors
|
|
183
|
+
- **Named:** 17 colors (red, blue, green, orange, purple, black, white, cyan, magenta, yellow, brown, pink, gray, olive, navy, teal, lime)
|
|
184
|
+
- **Shorthand:** `"r"`, `"g"`, `"b"`, `"c"`, `"m"`, `"y"`, `"k"`, `"w"`
|
|
185
|
+
- **Hex:** `"#FF0000"`, `"#f00"`, `"#FF000080"`
|
|
186
|
+
- **RGB/RGBA tuples:** `(1.0, 0.0, 0.0)`, `(1.0, 0.0, 0.0, 0.5)`
|
|
187
|
+
|
|
188
|
+
### Linestyles & Markers
|
|
189
|
+
- **Linestyles:** `-` (solid), `--` (dashed), `-.` (dashdot), `:` (dotted)
|
|
190
|
+
- **Markers:** `.` `o` `s` `^` `v` `+` `x` `D` `*`
|
|
191
|
+
- **Format strings:** `"r--o"` = red + dashed + circle markers
|
|
192
|
+
- **markevery:** show marker every N points
|
|
193
|
+
|
|
194
|
+
### Colormaps (35+)
|
|
195
|
+
`viridis` `plasma` `inferno` `magma` `cividis` `twilight` `turbo` `hot` `cool` `gray` `jet` `spring` `summer` `autumn` `winter` `copper` `bone` `pink` `binary` `gist_heat` `ocean` `terrain` `Blues` `Reds` `Greens` `YlOrRd` `YlGnBu` `RdYlBu` `RdBu` `PiYG` `PRGn` `BrBG` `Spectral` `Set1` `Set2` `Set3` `Pastel1` `Pastel2` `tab20`
|
|
196
|
+
|
|
197
|
+
### Text Rendering
|
|
198
|
+
- Embedded DejaVu Sans font (no system font dependency)
|
|
199
|
+
- LaTeX-to-Unicode conversion (`$\theta$` -> theta, `$x_1$` -> x1, Greek letters, sub/superscripts, math operators)
|
|
200
|
+
|
|
201
|
+
### Data Integration
|
|
202
|
+
- **Pandas:** plot directly from DataFrame/Series (optional dependency)
|
|
203
|
+
- **NumPy:** full array support
|
|
204
|
+
- **NaN handling:** automatic gaps in line plots for NaN/Inf values
|
|
205
|
+
- **Dates:** `date2num()`, `num2date()`, date formatters and locators
|
|
206
|
+
- **Categorical axes:** string-based x values automatically converted
|
|
207
|
+
|
|
208
|
+
### Compatibility Modules
|
|
209
|
+
| Module | Status |
|
|
210
|
+
|---|---|
|
|
211
|
+
| `rustplotlib.pyplot` | Full implementation |
|
|
212
|
+
| `rustplotlib.style` | Full implementation (6 themes) |
|
|
213
|
+
| `rustplotlib.animation` | FuncAnimation + GIF export |
|
|
214
|
+
| `rustplotlib.widgets` | Stubs (Slider, Button, CheckButtons, RadioButtons, TextBox, Cursor) |
|
|
215
|
+
| `rustplotlib.font_manager` | FontProperties stub |
|
|
216
|
+
| `rustplotlib.ticker` | FormatStrFormatter stub |
|
|
217
|
+
| `rustplotlib.patches` | Rectangle, Circle, Polygon, FancyBboxPatch, Wedge |
|
|
218
|
+
| `rustplotlib.colors` | LinearSegmentedColormap, Normalize, LogNorm |
|
|
219
|
+
| `rustplotlib.dates` | Date conversion, formatters, locators |
|
|
220
|
+
| `rustplotlib.gridspec` | GridSpec, SubplotSpec |
|
|
221
|
+
| `rustplotlib.backends` | Backend system with `use()` |
|
|
222
|
+
| `rustplotlib.mpl_toolkits.mplot3d` | Axes3D for 3D plotting |
|
|
223
|
+
|
|
224
|
+
---
|
|
225
|
+
|
|
226
|
+
## Examples
|
|
227
|
+
|
|
228
|
+
### Subplots
|
|
229
|
+
|
|
230
|
+
```python
|
|
231
|
+
import rustplotlib.pyplot as plt
|
|
232
|
+
import numpy as np
|
|
233
|
+
|
|
234
|
+
fig, axes = plt.subplots(2, 2, figsize=(10, 8))
|
|
235
|
+
|
|
236
|
+
x = np.linspace(0, 10, 100)
|
|
237
|
+
axes[0][0].plot(x, np.sin(x), label="sin(x)")
|
|
238
|
+
axes[0][0].plot(x, np.cos(x), label="cos(x)", linestyle="--")
|
|
239
|
+
axes[0][0].set_title("Trigonometry")
|
|
240
|
+
axes[0][0].legend()
|
|
241
|
+
axes[0][0].grid(True)
|
|
242
|
+
|
|
243
|
+
axes[0][1].scatter(np.random.randn(200), np.random.randn(200), alpha=0.5)
|
|
244
|
+
axes[0][1].set_title("Random Scatter")
|
|
245
|
+
|
|
246
|
+
axes[1][0].bar([1, 2, 3, 4, 5], [3, 7, 2, 5, 8], color="green")
|
|
247
|
+
axes[1][0].set_title("Bar Chart")
|
|
248
|
+
|
|
249
|
+
axes[1][1].hist(np.random.randn(5000), bins=40, color="orange")
|
|
250
|
+
axes[1][1].set_title("Distribution")
|
|
251
|
+
|
|
252
|
+
fig.savefig("subplots.png")
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
### 3D Surface Plot
|
|
256
|
+
|
|
257
|
+
```python
|
|
258
|
+
import rustplotlib.pyplot as plt
|
|
259
|
+
import numpy as np
|
|
260
|
+
|
|
261
|
+
fig = plt.figure(figsize=(10, 8))
|
|
262
|
+
ax = fig.add_subplot(111, projection='3d')
|
|
263
|
+
|
|
264
|
+
X = np.linspace(-5, 5, 50)
|
|
265
|
+
Y = np.linspace(-5, 5, 50)
|
|
266
|
+
X, Y = np.meshgrid(X, Y)
|
|
267
|
+
Z = np.sin(np.sqrt(X**2 + Y**2))
|
|
268
|
+
|
|
269
|
+
ax.plot_surface(X.tolist(), Y.tolist(), Z.tolist(), cmap='viridis')
|
|
270
|
+
ax.set_xlabel("X")
|
|
271
|
+
ax.set_ylabel("Y")
|
|
272
|
+
ax.set_zlabel("Z")
|
|
273
|
+
plt.savefig("surface3d.png")
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
### Dark Mode
|
|
277
|
+
|
|
278
|
+
```python
|
|
279
|
+
import rustplotlib.pyplot as plt
|
|
280
|
+
import rustplotlib.style as style
|
|
281
|
+
|
|
282
|
+
style.use('dark_background')
|
|
283
|
+
plt.plot([1, 2, 3, 4], [1, 4, 2, 3], 'c-o', linewidth=2)
|
|
284
|
+
plt.title("Dark Mode")
|
|
285
|
+
plt.savefig("dark.png")
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
### Animation
|
|
289
|
+
|
|
290
|
+
```python
|
|
291
|
+
import rustplotlib.pyplot as plt
|
|
292
|
+
from rustplotlib.animation import FuncAnimation
|
|
293
|
+
import numpy as np
|
|
294
|
+
|
|
295
|
+
fig, ax = plt.subplots()
|
|
296
|
+
x = np.linspace(0, 2 * np.pi, 100)
|
|
297
|
+
|
|
298
|
+
def update(frame):
|
|
299
|
+
ax.plot(x, np.sin(x + frame * 0.1), color='blue')
|
|
300
|
+
ax.set_title(f"Frame {frame}")
|
|
301
|
+
|
|
302
|
+
anim = FuncAnimation(fig, update, frames=50)
|
|
303
|
+
anim.save("wave.gif")
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
---
|
|
307
|
+
|
|
308
|
+
## Performance Benchmark
|
|
309
|
+
|
|
310
|
+
Benchmarked against matplotlib on Apple Silicon (M-series). Each test runs 10 iterations, averaged:
|
|
311
|
+
|
|
312
|
+
| Benchmark | matplotlib | rustplotlib | Speedup |
|
|
313
|
+
|---|---|---|---|
|
|
314
|
+
| Line Plot (10k points) | 0.064s | 0.002s | **30.8x** |
|
|
315
|
+
| Scatter (5k points) | 0.029s | 0.017s | **1.7x** |
|
|
316
|
+
| Bar Chart (50 bars) | 0.023s | 0.002s | **9.6x** |
|
|
317
|
+
| Histogram (100k points) | 0.081s | 0.003s | **27.9x** |
|
|
318
|
+
| Subplots 2x2 | 0.041s | 0.002s | **26.7x** |
|
|
319
|
+
|
|
320
|
+
Run the benchmark yourself:
|
|
321
|
+
```bash
|
|
322
|
+
python tests/test_benchmark.py
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
---
|
|
326
|
+
|
|
327
|
+
## Tech Stack
|
|
328
|
+
|
|
329
|
+
| Component | Technology | Purpose |
|
|
330
|
+
|---|---|---|
|
|
331
|
+
| 2D Rendering | [tiny-skia](https://github.com/nickel-org/tiny-skia) | Rasterization (paths, shapes, antialiasing) |
|
|
332
|
+
| SVG Rendering | Custom SVG renderer | Native vector SVG output |
|
|
333
|
+
| Fonts | [ab_glyph](https://github.com/alexheretic/ab-glyph) | Text rendering with embedded DejaVu Sans |
|
|
334
|
+
| PNG output | [png](https://crates.io/crates/png) | PNG encoding |
|
|
335
|
+
| Window | [winit](https://github.com/rust-windowing/winit) + [softbuffer](https://github.com/rust-windowing/softbuffer) | Interactive display |
|
|
336
|
+
| 3D Projection | Custom | Orthographic 3D-to-2D with camera control |
|
|
337
|
+
| Python bindings | [PyO3](https://pyo3.rs/) + [maturin](https://www.maturin.rs/) | Rust-to-Python bridge |
|
|
338
|
+
| NumPy interop | [numpy](https://crates.io/crates/numpy) (PyO3) | Array conversion |
|
|
339
|
+
|
|
340
|
+
---
|
|
341
|
+
|
|
342
|
+
## Architecture
|
|
343
|
+
|
|
344
|
+
```
|
|
345
|
+
Python: import rustplotlib.pyplot as plt
|
|
346
|
+
|
|
|
347
|
+
v
|
|
348
|
+
pyplot.py (matplotlib-compatible API layer)
|
|
349
|
+
|
|
|
350
|
+
v
|
|
351
|
+
PyO3 bridge (Rust <-> Python)
|
|
352
|
+
|
|
|
353
|
+
v
|
|
354
|
+
Rust core:
|
|
355
|
+
Figure --> Axes (2D) ---------> Artists (Line2D, Scatter, Bar, ...)
|
|
356
|
+
| |
|
|
357
|
+
--> Axes3D -----------> Artists3D (Line3D, Surface3D, ...)
|
|
358
|
+
|
|
|
359
|
+
v
|
|
360
|
+
Transform / Camera
|
|
361
|
+
|
|
|
362
|
+
+------------+------------+
|
|
363
|
+
| | |
|
|
364
|
+
tiny-skia SvgRenderer PDF gen
|
|
365
|
+
(raster) (vector) (document)
|
|
366
|
+
| | |
|
|
367
|
+
PNG SVG PDF
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
---
|
|
371
|
+
|
|
372
|
+
## Security
|
|
373
|
+
|
|
374
|
+
- **Zero `unsafe` blocks** in the entire Rust codebase
|
|
375
|
+
- Path validation in `savefig()` (extension whitelist, path traversal rejection)
|
|
376
|
+
- Dimension validation (max 32768x32768 pixels)
|
|
377
|
+
- Unique temp file names (no symlink race conditions)
|
|
378
|
+
- Input validation on all PyO3 boundaries
|
|
379
|
+
- No `.unwrap()` on user-controlled data — proper error handling throughout
|
|
380
|
+
|
|
381
|
+
---
|
|
382
|
+
|
|
383
|
+
## Contributing
|
|
384
|
+
|
|
385
|
+
Contributions are welcome! This is an open-source project under the MIT license.
|
|
386
|
+
|
|
387
|
+
1. Fork the repo
|
|
388
|
+
2. Create a feature branch
|
|
389
|
+
3. Open a PR against `master`
|
|
390
|
+
4. PRs require at least 1 review before merging
|
|
391
|
+
|
|
392
|
+
**Priority areas for contribution:**
|
|
393
|
+
- Turning stub modules into full implementations (widgets, formatters/locators)
|
|
394
|
+
- Adding more colormaps with exact matplotlib data
|
|
395
|
+
- Improving SVG output fidelity
|
|
396
|
+
- Jupyter inline display support
|
|
397
|
+
- More comprehensive test coverage
|
|
398
|
+
|
|
399
|
+
---
|
|
400
|
+
|
|
401
|
+
## License
|
|
402
|
+
|
|
403
|
+
[MIT](LICENSE)
|
|
404
|
+
|