rustplotlib 5.0.0__tar.gz → 5.1.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 (148) hide show
  1. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/CLAUDE.md +5 -5
  2. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/Cargo.lock +1 -1
  3. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/Cargo.toml +1 -1
  4. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/PKG-INFO +121 -56
  5. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/README.md +119 -54
  6. rustplotlib-5.1.0/ROADMAP.md +220 -0
  7. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/pyproject.toml +2 -2
  8. rustplotlib-5.1.0/python/rustplotlib/animation.py +221 -0
  9. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/python/rustplotlib/backends/__init__.py +6 -0
  10. rustplotlib-5.1.0/python/rustplotlib/backends/backend_pdf.py +152 -0
  11. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/python/rustplotlib/backends/backend_tk.py +55 -0
  12. rustplotlib-5.1.0/python/rustplotlib/backends/backend_webagg.py +292 -0
  13. rustplotlib-5.1.0/python/rustplotlib/collections.py +112 -0
  14. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/python/rustplotlib/colors.py +65 -0
  15. rustplotlib-5.1.0/python/rustplotlib/dates.py +237 -0
  16. rustplotlib-5.1.0/python/rustplotlib/gridspec.py +75 -0
  17. rustplotlib-5.1.0/python/rustplotlib/mpl_toolkits/axes_grid1/__init__.py +5 -0
  18. rustplotlib-5.1.0/python/rustplotlib/mpl_toolkits/axes_grid1/axes_divider.py +89 -0
  19. rustplotlib-5.1.0/python/rustplotlib/patheffects.py +111 -0
  20. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/python/rustplotlib/pyplot.py +1621 -99
  21. rustplotlib-5.1.0/python/rustplotlib/pyplot.pyi +223 -0
  22. rustplotlib-5.1.0/python/rustplotlib/style/__init__.py +174 -0
  23. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/python/rustplotlib/ticker.py +17 -40
  24. rustplotlib-5.1.0/python/rustplotlib/transforms.py +166 -0
  25. rustplotlib-5.1.0/python/rustplotlib/widgets.py +399 -0
  26. rustplotlib-5.1.0/src/artists/colorbar_artist.rs +201 -0
  27. rustplotlib-5.1.0/src/artists/fancy_arrow.rs +319 -0
  28. rustplotlib-5.1.0/src/artists/image.rs +1775 -0
  29. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/src/artists/line2d.rs +158 -13
  30. rustplotlib-5.1.0/src/artists/line_collection.rs +113 -0
  31. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/src/artists/mod.rs +215 -0
  32. rustplotlib-5.1.0/src/artists/widget.rs +203 -0
  33. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/src/axes.rs +421 -72
  34. rustplotlib-5.1.0/src/colors.rs +285 -0
  35. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/src/figure.rs +731 -38
  36. rustplotlib-5.1.0/src/lib.rs +85 -0
  37. rustplotlib-5.1.0/src/mathtext.rs +703 -0
  38. rustplotlib-5.1.0/src/parse.rs +374 -0
  39. rustplotlib-5.1.0/src/projections.rs +240 -0
  40. rustplotlib-5.1.0/src/transforms.rs +245 -0
  41. rustplotlib-5.1.0/tests/test_advanced_customization.py +118 -0
  42. rustplotlib-5.1.0/tests/test_axes_figure_api.py +286 -0
  43. rustplotlib-5.1.0/tests/test_colorbar_annotations.py +148 -0
  44. rustplotlib-5.1.0/tests/test_colormaps.py +92 -0
  45. rustplotlib-5.1.0/tests/test_layout.py +137 -0
  46. rustplotlib-5.1.0/tests/test_markers.py +90 -0
  47. rustplotlib-5.1.0/tests/test_output_formats.py +88 -0
  48. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/tests/test_phase8.py +17 -15
  49. rustplotlib-5.1.0/tests/test_polar.py +160 -0
  50. rustplotlib-5.1.0/tests/test_regression.py +204 -0
  51. rustplotlib-5.1.0/tests/test_spine_positioning.py +180 -0
  52. rustplotlib-5.1.0/tests/test_styles.py +121 -0
  53. rustplotlib-5.1.0/tests/test_triangulation.py +171 -0
  54. rustplotlib-5.1.0/tests/test_v5_features.py +744 -0
  55. rustplotlib-5.1.0/tests/test_widgets.py +259 -0
  56. rustplotlib-5.0.0/ROADMAP.md +0 -200
  57. rustplotlib-5.0.0/python/rustplotlib/animation.py +0 -94
  58. rustplotlib-5.0.0/python/rustplotlib/backends/backend_pdf.py +0 -56
  59. rustplotlib-5.0.0/python/rustplotlib/collections.py +0 -70
  60. rustplotlib-5.0.0/python/rustplotlib/dates.py +0 -87
  61. rustplotlib-5.0.0/python/rustplotlib/gridspec.py +0 -30
  62. rustplotlib-5.0.0/python/rustplotlib/patheffects.py +0 -36
  63. rustplotlib-5.0.0/python/rustplotlib/pyplot.pyi +0 -96
  64. rustplotlib-5.0.0/python/rustplotlib/style/__init__.py +0 -70
  65. rustplotlib-5.0.0/python/rustplotlib/transforms.py +0 -68
  66. rustplotlib-5.0.0/python/rustplotlib/widgets.py +0 -75
  67. rustplotlib-5.0.0/src/artists/image.rs +0 -757
  68. rustplotlib-5.0.0/src/colors.rs +0 -161
  69. rustplotlib-5.0.0/src/lib.rs +0 -47
  70. rustplotlib-5.0.0/src/transforms.rs +0 -104
  71. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/.github/workflows/ci.yml +0 -0
  72. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/.gitignore +0 -0
  73. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/CONTRIBUTING.md +0 -0
  74. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/LICENSE +0 -0
  75. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/benchmark_results.csv +0 -0
  76. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/dados/Data/PerfisTemp_rustplotlib.py +0 -0
  77. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/docs/superpowers/plans/2026-04-04-jupyter-and-event-foundation.md +0 -0
  78. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/python/rustplotlib/__init__.py +0 -0
  79. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/python/rustplotlib/axes/__init__.py +0 -0
  80. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/python/rustplotlib/backends/backend_base.py +0 -0
  81. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/python/rustplotlib/backends/backend_inline.py +0 -0
  82. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/python/rustplotlib/callback_registry.py +0 -0
  83. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/python/rustplotlib/cm.py +0 -0
  84. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/python/rustplotlib/cycler.py +0 -0
  85. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/python/rustplotlib/events.py +0 -0
  86. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/python/rustplotlib/figure.py +0 -0
  87. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/python/rustplotlib/font_manager.py +0 -0
  88. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/python/rustplotlib/lines.py +0 -0
  89. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/python/rustplotlib/mpl_toolkits/__init__.py +0 -0
  90. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/python/rustplotlib/mpl_toolkits/mplot3d/__init__.py +0 -0
  91. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/python/rustplotlib/patches.py +0 -0
  92. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/python/rustplotlib/spines.py +0 -0
  93. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/python/rustplotlib/text.py +0 -0
  94. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/src/artists/arrow.rs +0 -0
  95. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/src/artists/bar.rs +0 -0
  96. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/src/artists/bar3d.rs +0 -0
  97. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/src/artists/barh.rs +0 -0
  98. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/src/artists/boxplot.rs +0 -0
  99. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/src/artists/broken_barh.rs +0 -0
  100. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/src/artists/contour.rs +0 -0
  101. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/src/artists/contour3d.rs +0 -0
  102. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/src/artists/errorbar.rs +0 -0
  103. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/src/artists/eventplot.rs +0 -0
  104. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/src/artists/fill_between.rs +0 -0
  105. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/src/artists/fill_betweenx.rs +0 -0
  106. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/src/artists/fill_polygon.rs +0 -0
  107. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/src/artists/hexbin.rs +0 -0
  108. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/src/artists/hist.rs +0 -0
  109. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/src/artists/legend.rs +0 -0
  110. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/src/artists/line3d.rs +0 -0
  111. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/src/artists/patches.rs +0 -0
  112. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/src/artists/pcolormesh.rs +0 -0
  113. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/src/artists/pie.rs +0 -0
  114. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/src/artists/quiver.rs +0 -0
  115. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/src/artists/radar.rs +0 -0
  116. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/src/artists/sankey.rs +0 -0
  117. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/src/artists/scatter.rs +0 -0
  118. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/src/artists/scatter3d.rs +0 -0
  119. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/src/artists/stem.rs +0 -0
  120. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/src/artists/step.rs +0 -0
  121. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/src/artists/streamplot.rs +0 -0
  122. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/src/artists/surface3d.rs +0 -0
  123. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/src/artists/trisurf3d.rs +0 -0
  124. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/src/artists/violin.rs +0 -0
  125. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/src/artists/wireframe3d.rs +0 -0
  126. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/src/axes3d.rs +0 -0
  127. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/src/fonts/DejaVuSans.ttf +0 -0
  128. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/src/projection3d.rs +0 -0
  129. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/src/svg_renderer.rs +0 -0
  130. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/src/text.rs +0 -0
  131. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/src/ticker.rs +0 -0
  132. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/src/window.rs +0 -0
  133. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/tests/test_3d.py +0 -0
  134. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/tests/test_backend_tk.py +0 -0
  135. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/tests/test_benchmark.py +0 -0
  136. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/tests/test_colors.py +0 -0
  137. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/tests/test_events.py +0 -0
  138. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/tests/test_figure.py +0 -0
  139. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/tests/test_jupyter_repr.py +0 -0
  140. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/tests/test_new_features.py +0 -0
  141. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/tests/test_new_features2.py +0 -0
  142. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/tests/test_phase6_7.py +0 -0
  143. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/tests/test_phase9_features.py +0 -0
  144. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/tests/test_pyplot.py +0 -0
  145. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/tests/test_spectral_features.py +0 -0
  146. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/tests/test_ticker.py +0 -0
  147. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/tests/test_transforms.py +0 -0
  148. {rustplotlib-5.0.0 → rustplotlib-5.1.0}/tests/test_v3_features.py +0 -0
@@ -11,10 +11,11 @@ Reimplementação completa do matplotlib em Rust puro. Drop-in replacement via P
11
11
  - 40+ plot types 2D, 7 plot types 3D
12
12
  - 70+ colormaps (35 base + 35 reversed)
13
13
  - 25 módulos Python compatíveis com API matplotlib
14
- - 298 testes passando
15
- - Tk backend interativo com toolbar, eventos de mouse/teclado e navegação
14
+ - 550+ testes passando
15
+ - Tk backend interativo com toolbar, zoom/pan funcional, pixel-to-data mapping
16
16
  - Jupyter rich display (`_repr_png_`, `_repr_svg_`, `_repr_html_`)
17
17
  - Sistema de eventos com `CallbackRegistry` e `mpl_connect`/`mpl_disconnect`
18
+ - Widgets funcionais: Slider, Button, CheckButtons, RadioButtons, TextBox, RangeSlider
18
19
  - Backend auto-detection (inline/tk/agg)
19
20
  - Output: PNG (tiny-skia), SVG nativo, PDF, GIF, janela interativa
20
21
  - Performance: até 16x mais rápido que matplotlib (benchmark real com 12 testes)
@@ -51,7 +52,7 @@ python/rustplotlib/ # Camada Python
51
52
  ├── dates.py, colors.py, patches.py, ...
52
53
  └── mpl_toolkits/mplot3d/ # Suporte 3D
53
54
 
54
- tests/ # Testes Python (298 testes)
55
+ tests/ # Testes Python (326 testes)
55
56
  ```
56
57
 
57
58
  ## Stack Técnica
@@ -107,8 +108,7 @@ cargo check # Verificar compilação Rust
107
108
  Próximos itens prioritários (ver ROADMAP.md para lista completa):
108
109
 
109
110
  1. **Backends adicionais** — Qt, GTK, WebAgg, macOS native
110
- 2. **Widgets funcionais** — Slider, Button, CheckButtons com renderização real
111
- 3. **Features interativas** — pick events, rotação 3D, blitting
111
+ 2. **Features interativas** — pick events, rotação 3D, blitting
112
112
  4. **Triangulation plots** — tricontour, tricontourf, tripcolor (atualmente stubs)
113
113
  5. **Customização avançada** — spine positioning, TwoSlopeNorm, interpolação bicúbica
114
114
 
@@ -1368,7 +1368,7 @@ dependencies = [
1368
1368
 
1369
1369
  [[package]]
1370
1370
  name = "rustplotlib"
1371
- version = "5.0.0"
1371
+ version = "5.1.0"
1372
1372
  dependencies = [
1373
1373
  "ab_glyph",
1374
1374
  "numpy",
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "rustplotlib"
3
- version = "5.0.0"
3
+ version = "5.1.0"
4
4
  edition = "2021"
5
5
  readme = "README.md"
6
6
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rustplotlib
3
- Version: 5.0.0
3
+ Version: 5.1.0
4
4
  Classifier: Development Status :: 3 - Alpha
5
5
  Classifier: Intended Audience :: Science/Research
6
6
  Classifier: License :: OSI Approved :: MIT License
@@ -9,7 +9,7 @@ Classifier: Programming Language :: Python :: 3
9
9
  Classifier: Topic :: Scientific/Engineering :: Visualization
10
10
  Requires-Dist: numpy
11
11
  License-File: LICENSE
12
- Summary: Matplotlib drop-in replacement powered by Rust
12
+ Summary: Matplotlib drop-in replacement powered by Rust — 50 plot types, 15 interpolation modes, 81 colormaps, up to 18.7x faster
13
13
  Keywords: matplotlib,plotting,visualization,rust,performance
14
14
  License: MIT
15
15
  Requires-Python: >=3.9
@@ -37,7 +37,7 @@ No Python runtime dependency for rendering. No wrappers. No subprocess calls. Pu
37
37
  |---|---|---|---|
38
38
  | Rendering engine | C/C++ (AGG) | None (wrap matplotlib or call Python) | **Rust native (tiny-skia)** |
39
39
  | External dependencies | NumPy, Pillow, FreeType, etc. | Python + matplotlib required | **Zero** — self-contained |
40
- | Performance | Baseline | Same or slower (subprocess overhead) | **Up to 16x faster** |
40
+ | Performance | Baseline | Same or slower (subprocess overhead) | **Up to 18.7x faster** |
41
41
  | Python API | Original | Rust-only or generates .py scripts | **Drop-in replacement** — same API |
42
42
  | Approach | Interpreted + C extensions | Wrappers / code generators | **Full reimplementation in Rust** |
43
43
 
@@ -195,62 +195,121 @@ plt.show()
195
195
  ### Output Formats
196
196
  | Method | Description |
197
197
  |---|---|
198
- | `savefig("file.png")` | Raster PNG (with dpi, transparent options) |
198
+ | `savefig("file.png")` | Raster PNG (with dpi, transparent, bbox_inches='tight') |
199
199
  | `savefig("file.svg")` | Native vector SVG (real `<line>`, `<text>`, `<rect>` elements) |
200
200
  | `savefig("file.pdf")` | PDF output |
201
- | `show()` | Interactive window with backend auto-detection (Tk/inline/agg) |
202
- | `PdfPages` | Multi-page PDF export |
201
+ | `savefig("file.eps")` | EPS output |
202
+ | `show()` | Interactive window with backend auto-detection |
203
+ | `PdfPages` | Multi-page PDF with zlib compression |
204
+ | `pickle` | Save/load figures with pickle |
205
+ | `copy_to_clipboard()` | Copy figure as PNG to system clipboard |
206
+ | `to_json()` / `save_json()` | Export figure state as JSON |
203
207
 
204
208
  ### Backends & Interactive
205
209
  | Feature | Description |
206
210
  |---|---|
207
211
  | Backend auto-detection | Automatically selects inline (Jupyter), Tk, or Agg backend |
208
- | Tk backend | Interactive window with `PhotoImage` rendering (640x480) |
209
- | Navigation toolbar | Home, Back, Forward, Pan, Zoom, Save + status bar (7 widgets) |
212
+ | Tk backend | Interactive window with toolbar, zoom/pan, coordinate display |
213
+ | WebAgg backend | Browser-based interactive viewer via HTTP server |
214
+ | Navigation toolbar | Home, Back, Forward, Pan, Zoom, Save (Tk + WebAgg) |
210
215
  | Event system | `mpl_connect` / `mpl_disconnect` with `CallbackRegistry` |
211
- | Mouse events | `MouseEvent` with button, x/y data, key modifiers |
212
- | Key events | `KeyEvent` for keyboard interaction |
213
- | Draw/Resize/Close events | `DrawEvent`, `ResizeEvent`, `CloseEvent` |
216
+ | Pick events | Artist hit testing backed by Rust (`hit_test_points`, `hit_test_line`) |
217
+ | Mouse/Key/Scroll events | Full event hierarchy: MouseEvent, KeyEvent, PickEvent, DrawEvent, ResizeEvent, CloseEvent |
214
218
  | Jupyter rich display | `_repr_png_()`, `_repr_svg_()`, `_repr_html_()` on Figure |
215
- | `render_to_svg_string()` | SVG output as string (PyO3) for Jupyter inline |
216
- | `render_to_rgba_buffer()` | Raw RGBA buffer (PyO3) for interactive backends |
219
+ | 3D mouse rotation | Drag to rotate 3D view in Tk backend |
217
220
 
218
221
  ### Animation
219
222
  | Feature | Description |
220
223
  |---|---|
221
- | `FuncAnimation` | Function-based animation with frame generation |
224
+ | `FuncAnimation` | Function-based animation with blit support, pause/resume |
225
+ | `ArtistAnimation` | Frame-based animation from artist lists |
222
226
  | GIF export | Save animations as GIF (via Pillow) |
223
- | PNG sequence | Save animation frames as individual PNGs |
227
+ | Live animation | Real-time animation in Tk backend |
228
+
229
+ ### Layout Engines
230
+ | Feature | Description |
231
+ |---|---|
232
+ | `tight_layout()` | Dynamic margins from text measurement (Rust) |
233
+ | `constrained_layout=True` | Constraint-based layout engine (Rust) |
234
+ | `GridSpec(nrows, ncols)` | Grid layout with `rowspan`/`colspan` |
235
+ | `SubFigure` | Nested sub-figures with independent layouts |
236
+ | `Figure.add_axes([l,b,w,h])` | Custom axes positioning |
237
+ | `make_axes_locatable` | Axes divider for colorbar positioning |
238
+
239
+ ### Widgets (Rust-rendered)
240
+ | Widget | Features |
241
+ |---|---|
242
+ | `Slider` | Track, thumb circle, label, value display, on_changed callbacks |
243
+ | `RangeSlider` | Tuple values, clamp, callbacks |
244
+ | `Button` | Background, border, label, on_clicked callbacks |
245
+ | `CheckButtons` | Toggle, get_status, callbacks |
246
+ | `RadioButtons` | Exclusive selection, value_selected |
247
+ | `TextBox` | on_submit, on_text_change, set_val |
248
+ | `Cursor` | Crosshair following mouse, on_moved callbacks |
249
+ | `MultiCursor` | Cursor spanning multiple axes |
250
+
251
+ ### Transform System
252
+ | Component | Description |
253
+ |---|---|
254
+ | `Affine2D` | 2D affine matrix (rotate, scale, translate, compose, invert) — **Rust** |
255
+ | `BlendedTransform` | Separate X/Y transforms — **Rust** |
256
+ | `ax.transData` | Data coordinate transform |
257
+ | `ax.transAxes` | Axes coordinate transform (0-1) |
258
+ | `fig.transFigure` | Figure coordinate transform |
224
259
 
225
260
  ### Styles & Themes
226
261
  | Feature | Description |
227
262
  |---|---|
228
- | `style.use('dark_background')` | 6 built-in themes (default, dark_background, ggplot, seaborn, bmh, fivethirtyeight) |
263
+ | `style.use('dark_background')` | 13 built-in themes (default, dark_background, ggplot, seaborn, bmh, fivethirtyeight, grayscale, Solarize_Light2, tableau-colorblind10, seaborn-whitegrid, seaborn-darkgrid, seaborn-dark, fast) |
264
+ | `style.available` | List all available styles |
265
+ | `style.context('ggplot')` | Context manager for temporary style |
229
266
  | `rcParams` | Functional global configuration (30+ supported keys) |
230
267
  | `set_facecolor()` | Figure and axes background colors |
231
268
 
232
269
  ### Colors
233
- - **Named:** 17 colors (red, blue, green, orange, purple, black, white, cyan, magenta, yellow, brown, pink, gray, olive, navy, teal, lime)
270
+ - **Named:** 140+ colors including all CSS/X11 colors (steelblue, coral, tomato, gold, crimson, dodgerblue, forestgreen, etc.)
234
271
  - **Shorthand:** `"r"`, `"g"`, `"b"`, `"c"`, `"m"`, `"y"`, `"k"`, `"w"`
235
272
  - **Hex:** `"#FF0000"`, `"#f00"`, `"#FF000080"`
236
273
  - **RGB/RGBA tuples:** `(1.0, 0.0, 0.0)`, `(1.0, 0.0, 0.0, 0.5)`
274
+ - **Grey/gray variants:** both spellings supported
237
275
 
238
276
  ### Linestyles & Markers
239
277
  - **Linestyles:** `-` (solid), `--` (dashed), `-.` (dashdot), `:` (dotted)
240
- - **Markers:** `.` `o` `s` `^` `v` `+` `x` `D` `*`
241
- - **Format strings:** `"r--o"` = red + dashed + circle markers
278
+ - **Markers:** `.` `o` `s` `^` `v` `<` `>` `+` `x` `D` `d` `*` `p` `h` `H` `8` `|` `_` `P` `X` `1` `2` `3` `4` (24 types)
279
+ - **Format strings:** `"r--o"` = red + dashed + circle markers (parsed in Rust)
242
280
  - **markevery:** show marker every N points
243
281
 
244
- ### Colormaps (70+)
245
- 35 base colormaps + all reversed variants (`_r` suffix):
282
+ ### Colormaps (81 base + reversed = ~162 total)
283
+ `viridis` `plasma` `inferno` `magma` `cividis` `twilight` `twilight_shifted` `turbo` `hot` `cool` `coolwarm` `bwr` `seismic` `gray` `jet` `spring` `summer` `autumn` `winter` `copper` `bone` `pink` `binary` `ocean` `terrain` `rainbow` `Blues` `Reds` `Greens` `Oranges` `Purples` `Greys` `YlOrRd` `YlOrBr` `YlGnBu` `YlGn` `OrRd` `BuGn` `BuPu` `GnBu` `PuBu` `PuRd` `RdPu` `PuBuGn` `RdYlBu` `RdBu` `RdGy` `RdYlGn` `PiYG` `PRGn` `BrBG` `PuOr` `Spectral` `Set1` `Set2` `Set3` `Pastel1` `Pastel2` `tab10` `tab20` `tab20b` `tab20c` `Paired` `Accent` `Dark2` `afmhot` `brg` `CMRmap` `Wistia` `cubehelix` `hsv` `gnuplot` `gnuplot2` `gist_earth` `gist_heat` `gist_ncar` `gist_rainbow` `gist_stern` `gist_yarg` `flag` `prism`
246
284
 
247
- `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`
285
+ All also available reversed with `_r` suffix.
248
286
 
249
- All also available as `viridis_r`, `plasma_r`, `hot_r`, etc.
287
+ ### Image Interpolation (15 modes)
288
+ `nearest` `bilinear` `bicubic` `lanczos` `spline16` `hanning` `hamming` `hermite` `kaiser` `quadric` `catrom` `gaussian` `bessel` `mitchell` `sinc`
250
289
 
251
- ### Text Rendering
290
+ ### Text & Math Rendering
252
291
  - Embedded DejaVu Sans font (no system font dependency)
253
- - LaTeX-to-Unicode conversion (`$\theta$` -> theta, `$x_1$` -> x1, Greek letters, sub/superscripts, math operators)
292
+ - **Full TeX math engine in Rust:**
293
+ - Greek letters (24 lowercase + 12 uppercase)
294
+ - Subscript/superscript with Unicode characters
295
+ - Stacked fractions (`\frac{a}{b}`) with horizontal bar
296
+ - Square roots (`\sqrt{x}`) with radical sign
297
+ - Integral/sum/product with limits (`\int_a^b`, `\sum_{i=0}^n`)
298
+ - Accents: `\hat`, `\tilde`, `\vec`, `\dot`, `\ddot`, `\overline`, `\underline`
299
+ - Delimiters: `\left(`, `\right)`, `\langle`, `\rangle`, `\lceil`, `\lfloor`
300
+ - Matrices with bracket rendering
301
+ - 60+ math operators and symbols
302
+
303
+ ### Geographic Projections (5 types)
304
+ | Projection | Function |
305
+ |---|---|
306
+ | Hammer | `hammer_project(lon, lat)` |
307
+ | Aitoff | `aitoff_project(lon, lat)` |
308
+ | Mollweide | `mollweide_project(lon, lat)` |
309
+ | Lambert Conformal Conic | `lambert_project(lon, lat, lat1, lat2)` |
310
+ | Stereographic | `stereographic_project(lon, lat, lon0, lat0)` |
311
+
312
+ All with batch versions and `generate_graticule()` for grid lines.
254
313
 
255
314
  ### Data Integration
256
315
  - **Pandas:** plot directly from DataFrame/Series (optional dependency)
@@ -265,7 +324,7 @@ All also available as `viridis_r`, `plasma_r`, `hot_r`, etc.
265
324
  | `rustplotlib.pyplot` | Full implementation (50+ functions) |
266
325
  | `rustplotlib.style` | Full implementation (6 themes) |
267
326
  | `rustplotlib.animation` | FuncAnimation + GIF export |
268
- | `rustplotlib.widgets` | Stubs (Slider, Button, CheckButtons, RadioButtons, TextBox, Cursor) |
327
+ | `rustplotlib.widgets` | Functional (Slider, Button, CheckButtons, RadioButtons, TextBox, RangeSlider, Cursor) |
269
328
  | `rustplotlib.font_manager` | FontProperties |
270
329
  | `rustplotlib.ticker` | 12 Formatters + 10 Locators (functional) |
271
330
  | `rustplotlib.patches` | Rectangle, Circle, Polygon, FancyBboxPatch, Wedge, FancyArrowPatch |
@@ -375,25 +434,29 @@ anim.save("wave.gif")
375
434
 
376
435
  ## Performance Benchmark
377
436
 
378
- Benchmarked against matplotlib on Apple Silicon (M-series). Each test runs 10 iterations, averaged:
437
+ Benchmarked against matplotlib on Apple Silicon (M-series, release build). Each test runs 10 iterations, averaged:
379
438
 
380
439
  | Benchmark | matplotlib | rustplotlib | Speedup |
381
440
  |---|---|---|---|
382
- | Line Plot (10k pts) | 0.028s | 0.005s | **5.3x** |
383
- | Scatter (5k pts) | 0.028s | 0.021s | **1.4x** |
384
- | Bar Chart (50 bars) | 0.026s | 0.005s | **5.0x** |
385
- | Histogram (100k pts) | 0.090s | 0.006s | **16.1x** |
386
- | Subplots 2x2 | 0.046s | 0.011s | **4.2x** |
387
- | Heatmap (100x100) | 0.021s | 0.006s | **3.4x** |
388
- | Large Line (100k pts) | 0.110s | 0.109s | **1.0x** |
389
- | Multi-line (20 lines) | 0.090s | 0.037s | **2.4x** |
390
- | Error Bars | 0.022s | 0.004s | **6.4x** |
391
- | Pie Chart | 0.012s | 0.005s | **2.7x** |
392
- | SVG Output | 0.021s | 0.003s | **6.9x** |
393
- | Full Styled Plot | 0.019s | 0.006s | **3.4x** |
441
+ | Line Plot (10k pts) | 0.024s | 0.005s | **4.7x** |
442
+ | Scatter (5k pts) | 0.027s | 0.020s | **1.3x** |
443
+ | Bar Chart (50 bars) | 0.024s | 0.004s | **5.7x** |
444
+ | Histogram (100k pts) | 0.087s | 0.005s | **18.7x** |
445
+ | Subplots 2x2 | 0.038s | 0.010s | **3.9x** |
446
+ | Heatmap (100x100) | 0.019s | 0.005s | **3.7x** |
447
+ | Large Line (100k pts) | 0.109s | 0.110s | **1.0x** |
448
+ | Multi-line (20 lines) | 0.085s | 0.029s | **2.9x** |
449
+ | Error Bars | 0.021s | 0.004s | **5.9x** |
450
+ | Pie Chart | 0.009s | 0.004s | **2.4x** |
451
+ | SVG Output | 0.021s | 0.003s | **7.6x** |
452
+ | Full Styled Plot | 0.018s | 0.005s | **3.9x** |
453
+ | **TOTAL** | **0.481s** | **0.203s** | **2.4x** |
454
+
455
+ > Wins 11 out of 12 benchmarks. Up to **18.7x faster** on histogram rendering.
394
456
 
395
457
  Run the benchmark yourself:
396
458
  ```bash
459
+ maturin develop --release
397
460
  python tests/test_benchmark.py
398
461
  ```
399
462
 
@@ -465,25 +528,27 @@ Contributions are welcome! This is an open-source project under the MIT license.
465
528
  4. PRs require at least 1 review before merging
466
529
 
467
530
  **Project stats:**
468
- - **45+ Rust source files** — 23,000+ lines of native code
469
- - **25 Python modules** — 4,900+ lines of API
470
- - **47+ plot functions** (40 2D + 7 3D)
471
- - **70+ colormaps** (35 base + 35 reversed)
472
- - **298 tests** passing
473
- - **22 formatters + locators** (functional)
474
- - **Tk interactive backend** with navigation toolbar and event system
475
- - **Jupyter rich display** (`_repr_png_`, `_repr_svg_`, `_repr_html_`)
476
- - **Event system** with `mpl_connect` / `mpl_disconnect`
477
- - **RGB/RGBA imshow**, bilinear interpolation, heatmap annotations
478
- - **Signal processing**: specgram, psd, acorr, xcorr, coherence
531
+ - **53 Rust source files** — 30,000+ lines of native code
532
+ - **25+ Python modules** — thin PyO3 wrappers
533
+ - **50 plot types** (43 2D + 7 3D) — 100% of matplotlib plot types
534
+ - **81 colormaps** + reversed = ~162 total (~95% of matplotlib)
535
+ - **550+ tests** passing (including 27 rendering regression tests)
536
+ - **110/110 pyplot functions**, 95/95 Axes methods, 36/36 Figure methods
537
+ - **15 interpolation modes**: nearest, bilinear, bicubic, lanczos, spline16, hanning, hamming, hermite, kaiser, quadric, catrom, gaussian, bessel, mitchell, sinc
538
+ - **5 geographic projections**: Hammer, Aitoff, Mollweide, Lambert, Stereographic
539
+ - **4 backends**: Agg, Tk (interactive), Jupyter inline, WebAgg (browser)
540
+ - **4 output formats**: PNG, SVG, PDF (multi-page), EPS
541
+ - **Full TeX math engine**: Greek, sub/superscript, fractions, sqrt, matrices
542
+ - **Full transform system**: Affine2D, BlendedTransform, transData/transAxes
543
+ - **Full event system**: mouse, keyboard, pick events with Rust hit testing
544
+ - **Widgets**: Slider, Button, CheckButtons, RadioButtons, TextBox (Rust rendering)
545
+ - **Layout engines**: tight layout, constrained layout, GridSpec rowspan/colspan, SubFigure
479
546
  - **Zero `unsafe` blocks**
480
547
 
481
- **Priority areas for contribution:**
482
- - Qt/GTK backends
483
- - Functional widgets (Slider, Button, CheckButtons with real rendering)
484
- - 3D mouse rotation
485
- - Triangulation plots (tricontour, tripcolor)
486
- - LaTeX math rendering
548
+ **Remaining (need external dependencies):**
549
+ - Qt/GTK/macOS backends (need PyQt5, PyGObject, PyObjC)
550
+ - Math font rendering (need Computer Modern .ttf files)
551
+ - Basemap coastlines (need Natural Earth shapefiles)
487
552
 
488
553
  ---
489
554
 
@@ -17,7 +17,7 @@ No Python runtime dependency for rendering. No wrappers. No subprocess calls. Pu
17
17
  |---|---|---|---|
18
18
  | Rendering engine | C/C++ (AGG) | None (wrap matplotlib or call Python) | **Rust native (tiny-skia)** |
19
19
  | External dependencies | NumPy, Pillow, FreeType, etc. | Python + matplotlib required | **Zero** — self-contained |
20
- | Performance | Baseline | Same or slower (subprocess overhead) | **Up to 16x faster** |
20
+ | Performance | Baseline | Same or slower (subprocess overhead) | **Up to 18.7x faster** |
21
21
  | Python API | Original | Rust-only or generates .py scripts | **Drop-in replacement** — same API |
22
22
  | Approach | Interpreted + C extensions | Wrappers / code generators | **Full reimplementation in Rust** |
23
23
 
@@ -175,62 +175,121 @@ plt.show()
175
175
  ### Output Formats
176
176
  | Method | Description |
177
177
  |---|---|
178
- | `savefig("file.png")` | Raster PNG (with dpi, transparent options) |
178
+ | `savefig("file.png")` | Raster PNG (with dpi, transparent, bbox_inches='tight') |
179
179
  | `savefig("file.svg")` | Native vector SVG (real `<line>`, `<text>`, `<rect>` elements) |
180
180
  | `savefig("file.pdf")` | PDF output |
181
- | `show()` | Interactive window with backend auto-detection (Tk/inline/agg) |
182
- | `PdfPages` | Multi-page PDF export |
181
+ | `savefig("file.eps")` | EPS output |
182
+ | `show()` | Interactive window with backend auto-detection |
183
+ | `PdfPages` | Multi-page PDF with zlib compression |
184
+ | `pickle` | Save/load figures with pickle |
185
+ | `copy_to_clipboard()` | Copy figure as PNG to system clipboard |
186
+ | `to_json()` / `save_json()` | Export figure state as JSON |
183
187
 
184
188
  ### Backends & Interactive
185
189
  | Feature | Description |
186
190
  |---|---|
187
191
  | Backend auto-detection | Automatically selects inline (Jupyter), Tk, or Agg backend |
188
- | Tk backend | Interactive window with `PhotoImage` rendering (640x480) |
189
- | Navigation toolbar | Home, Back, Forward, Pan, Zoom, Save + status bar (7 widgets) |
192
+ | Tk backend | Interactive window with toolbar, zoom/pan, coordinate display |
193
+ | WebAgg backend | Browser-based interactive viewer via HTTP server |
194
+ | Navigation toolbar | Home, Back, Forward, Pan, Zoom, Save (Tk + WebAgg) |
190
195
  | Event system | `mpl_connect` / `mpl_disconnect` with `CallbackRegistry` |
191
- | Mouse events | `MouseEvent` with button, x/y data, key modifiers |
192
- | Key events | `KeyEvent` for keyboard interaction |
193
- | Draw/Resize/Close events | `DrawEvent`, `ResizeEvent`, `CloseEvent` |
196
+ | Pick events | Artist hit testing backed by Rust (`hit_test_points`, `hit_test_line`) |
197
+ | Mouse/Key/Scroll events | Full event hierarchy: MouseEvent, KeyEvent, PickEvent, DrawEvent, ResizeEvent, CloseEvent |
194
198
  | Jupyter rich display | `_repr_png_()`, `_repr_svg_()`, `_repr_html_()` on Figure |
195
- | `render_to_svg_string()` | SVG output as string (PyO3) for Jupyter inline |
196
- | `render_to_rgba_buffer()` | Raw RGBA buffer (PyO3) for interactive backends |
199
+ | 3D mouse rotation | Drag to rotate 3D view in Tk backend |
197
200
 
198
201
  ### Animation
199
202
  | Feature | Description |
200
203
  |---|---|
201
- | `FuncAnimation` | Function-based animation with frame generation |
204
+ | `FuncAnimation` | Function-based animation with blit support, pause/resume |
205
+ | `ArtistAnimation` | Frame-based animation from artist lists |
202
206
  | GIF export | Save animations as GIF (via Pillow) |
203
- | PNG sequence | Save animation frames as individual PNGs |
207
+ | Live animation | Real-time animation in Tk backend |
208
+
209
+ ### Layout Engines
210
+ | Feature | Description |
211
+ |---|---|
212
+ | `tight_layout()` | Dynamic margins from text measurement (Rust) |
213
+ | `constrained_layout=True` | Constraint-based layout engine (Rust) |
214
+ | `GridSpec(nrows, ncols)` | Grid layout with `rowspan`/`colspan` |
215
+ | `SubFigure` | Nested sub-figures with independent layouts |
216
+ | `Figure.add_axes([l,b,w,h])` | Custom axes positioning |
217
+ | `make_axes_locatable` | Axes divider for colorbar positioning |
218
+
219
+ ### Widgets (Rust-rendered)
220
+ | Widget | Features |
221
+ |---|---|
222
+ | `Slider` | Track, thumb circle, label, value display, on_changed callbacks |
223
+ | `RangeSlider` | Tuple values, clamp, callbacks |
224
+ | `Button` | Background, border, label, on_clicked callbacks |
225
+ | `CheckButtons` | Toggle, get_status, callbacks |
226
+ | `RadioButtons` | Exclusive selection, value_selected |
227
+ | `TextBox` | on_submit, on_text_change, set_val |
228
+ | `Cursor` | Crosshair following mouse, on_moved callbacks |
229
+ | `MultiCursor` | Cursor spanning multiple axes |
230
+
231
+ ### Transform System
232
+ | Component | Description |
233
+ |---|---|
234
+ | `Affine2D` | 2D affine matrix (rotate, scale, translate, compose, invert) — **Rust** |
235
+ | `BlendedTransform` | Separate X/Y transforms — **Rust** |
236
+ | `ax.transData` | Data coordinate transform |
237
+ | `ax.transAxes` | Axes coordinate transform (0-1) |
238
+ | `fig.transFigure` | Figure coordinate transform |
204
239
 
205
240
  ### Styles & Themes
206
241
  | Feature | Description |
207
242
  |---|---|
208
- | `style.use('dark_background')` | 6 built-in themes (default, dark_background, ggplot, seaborn, bmh, fivethirtyeight) |
243
+ | `style.use('dark_background')` | 13 built-in themes (default, dark_background, ggplot, seaborn, bmh, fivethirtyeight, grayscale, Solarize_Light2, tableau-colorblind10, seaborn-whitegrid, seaborn-darkgrid, seaborn-dark, fast) |
244
+ | `style.available` | List all available styles |
245
+ | `style.context('ggplot')` | Context manager for temporary style |
209
246
  | `rcParams` | Functional global configuration (30+ supported keys) |
210
247
  | `set_facecolor()` | Figure and axes background colors |
211
248
 
212
249
  ### Colors
213
- - **Named:** 17 colors (red, blue, green, orange, purple, black, white, cyan, magenta, yellow, brown, pink, gray, olive, navy, teal, lime)
250
+ - **Named:** 140+ colors including all CSS/X11 colors (steelblue, coral, tomato, gold, crimson, dodgerblue, forestgreen, etc.)
214
251
  - **Shorthand:** `"r"`, `"g"`, `"b"`, `"c"`, `"m"`, `"y"`, `"k"`, `"w"`
215
252
  - **Hex:** `"#FF0000"`, `"#f00"`, `"#FF000080"`
216
253
  - **RGB/RGBA tuples:** `(1.0, 0.0, 0.0)`, `(1.0, 0.0, 0.0, 0.5)`
254
+ - **Grey/gray variants:** both spellings supported
217
255
 
218
256
  ### Linestyles & Markers
219
257
  - **Linestyles:** `-` (solid), `--` (dashed), `-.` (dashdot), `:` (dotted)
220
- - **Markers:** `.` `o` `s` `^` `v` `+` `x` `D` `*`
221
- - **Format strings:** `"r--o"` = red + dashed + circle markers
258
+ - **Markers:** `.` `o` `s` `^` `v` `<` `>` `+` `x` `D` `d` `*` `p` `h` `H` `8` `|` `_` `P` `X` `1` `2` `3` `4` (24 types)
259
+ - **Format strings:** `"r--o"` = red + dashed + circle markers (parsed in Rust)
222
260
  - **markevery:** show marker every N points
223
261
 
224
- ### Colormaps (70+)
225
- 35 base colormaps + all reversed variants (`_r` suffix):
262
+ ### Colormaps (81 base + reversed = ~162 total)
263
+ `viridis` `plasma` `inferno` `magma` `cividis` `twilight` `twilight_shifted` `turbo` `hot` `cool` `coolwarm` `bwr` `seismic` `gray` `jet` `spring` `summer` `autumn` `winter` `copper` `bone` `pink` `binary` `ocean` `terrain` `rainbow` `Blues` `Reds` `Greens` `Oranges` `Purples` `Greys` `YlOrRd` `YlOrBr` `YlGnBu` `YlGn` `OrRd` `BuGn` `BuPu` `GnBu` `PuBu` `PuRd` `RdPu` `PuBuGn` `RdYlBu` `RdBu` `RdGy` `RdYlGn` `PiYG` `PRGn` `BrBG` `PuOr` `Spectral` `Set1` `Set2` `Set3` `Pastel1` `Pastel2` `tab10` `tab20` `tab20b` `tab20c` `Paired` `Accent` `Dark2` `afmhot` `brg` `CMRmap` `Wistia` `cubehelix` `hsv` `gnuplot` `gnuplot2` `gist_earth` `gist_heat` `gist_ncar` `gist_rainbow` `gist_stern` `gist_yarg` `flag` `prism`
226
264
 
227
- `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`
265
+ All also available reversed with `_r` suffix.
228
266
 
229
- All also available as `viridis_r`, `plasma_r`, `hot_r`, etc.
267
+ ### Image Interpolation (15 modes)
268
+ `nearest` `bilinear` `bicubic` `lanczos` `spline16` `hanning` `hamming` `hermite` `kaiser` `quadric` `catrom` `gaussian` `bessel` `mitchell` `sinc`
230
269
 
231
- ### Text Rendering
270
+ ### Text & Math Rendering
232
271
  - Embedded DejaVu Sans font (no system font dependency)
233
- - LaTeX-to-Unicode conversion (`$\theta$` -> theta, `$x_1$` -> x1, Greek letters, sub/superscripts, math operators)
272
+ - **Full TeX math engine in Rust:**
273
+ - Greek letters (24 lowercase + 12 uppercase)
274
+ - Subscript/superscript with Unicode characters
275
+ - Stacked fractions (`\frac{a}{b}`) with horizontal bar
276
+ - Square roots (`\sqrt{x}`) with radical sign
277
+ - Integral/sum/product with limits (`\int_a^b`, `\sum_{i=0}^n`)
278
+ - Accents: `\hat`, `\tilde`, `\vec`, `\dot`, `\ddot`, `\overline`, `\underline`
279
+ - Delimiters: `\left(`, `\right)`, `\langle`, `\rangle`, `\lceil`, `\lfloor`
280
+ - Matrices with bracket rendering
281
+ - 60+ math operators and symbols
282
+
283
+ ### Geographic Projections (5 types)
284
+ | Projection | Function |
285
+ |---|---|
286
+ | Hammer | `hammer_project(lon, lat)` |
287
+ | Aitoff | `aitoff_project(lon, lat)` |
288
+ | Mollweide | `mollweide_project(lon, lat)` |
289
+ | Lambert Conformal Conic | `lambert_project(lon, lat, lat1, lat2)` |
290
+ | Stereographic | `stereographic_project(lon, lat, lon0, lat0)` |
291
+
292
+ All with batch versions and `generate_graticule()` for grid lines.
234
293
 
235
294
  ### Data Integration
236
295
  - **Pandas:** plot directly from DataFrame/Series (optional dependency)
@@ -245,7 +304,7 @@ All also available as `viridis_r`, `plasma_r`, `hot_r`, etc.
245
304
  | `rustplotlib.pyplot` | Full implementation (50+ functions) |
246
305
  | `rustplotlib.style` | Full implementation (6 themes) |
247
306
  | `rustplotlib.animation` | FuncAnimation + GIF export |
248
- | `rustplotlib.widgets` | Stubs (Slider, Button, CheckButtons, RadioButtons, TextBox, Cursor) |
307
+ | `rustplotlib.widgets` | Functional (Slider, Button, CheckButtons, RadioButtons, TextBox, RangeSlider, Cursor) |
249
308
  | `rustplotlib.font_manager` | FontProperties |
250
309
  | `rustplotlib.ticker` | 12 Formatters + 10 Locators (functional) |
251
310
  | `rustplotlib.patches` | Rectangle, Circle, Polygon, FancyBboxPatch, Wedge, FancyArrowPatch |
@@ -355,25 +414,29 @@ anim.save("wave.gif")
355
414
 
356
415
  ## Performance Benchmark
357
416
 
358
- Benchmarked against matplotlib on Apple Silicon (M-series). Each test runs 10 iterations, averaged:
417
+ Benchmarked against matplotlib on Apple Silicon (M-series, release build). Each test runs 10 iterations, averaged:
359
418
 
360
419
  | Benchmark | matplotlib | rustplotlib | Speedup |
361
420
  |---|---|---|---|
362
- | Line Plot (10k pts) | 0.028s | 0.005s | **5.3x** |
363
- | Scatter (5k pts) | 0.028s | 0.021s | **1.4x** |
364
- | Bar Chart (50 bars) | 0.026s | 0.005s | **5.0x** |
365
- | Histogram (100k pts) | 0.090s | 0.006s | **16.1x** |
366
- | Subplots 2x2 | 0.046s | 0.011s | **4.2x** |
367
- | Heatmap (100x100) | 0.021s | 0.006s | **3.4x** |
368
- | Large Line (100k pts) | 0.110s | 0.109s | **1.0x** |
369
- | Multi-line (20 lines) | 0.090s | 0.037s | **2.4x** |
370
- | Error Bars | 0.022s | 0.004s | **6.4x** |
371
- | Pie Chart | 0.012s | 0.005s | **2.7x** |
372
- | SVG Output | 0.021s | 0.003s | **6.9x** |
373
- | Full Styled Plot | 0.019s | 0.006s | **3.4x** |
421
+ | Line Plot (10k pts) | 0.024s | 0.005s | **4.7x** |
422
+ | Scatter (5k pts) | 0.027s | 0.020s | **1.3x** |
423
+ | Bar Chart (50 bars) | 0.024s | 0.004s | **5.7x** |
424
+ | Histogram (100k pts) | 0.087s | 0.005s | **18.7x** |
425
+ | Subplots 2x2 | 0.038s | 0.010s | **3.9x** |
426
+ | Heatmap (100x100) | 0.019s | 0.005s | **3.7x** |
427
+ | Large Line (100k pts) | 0.109s | 0.110s | **1.0x** |
428
+ | Multi-line (20 lines) | 0.085s | 0.029s | **2.9x** |
429
+ | Error Bars | 0.021s | 0.004s | **5.9x** |
430
+ | Pie Chart | 0.009s | 0.004s | **2.4x** |
431
+ | SVG Output | 0.021s | 0.003s | **7.6x** |
432
+ | Full Styled Plot | 0.018s | 0.005s | **3.9x** |
433
+ | **TOTAL** | **0.481s** | **0.203s** | **2.4x** |
434
+
435
+ > Wins 11 out of 12 benchmarks. Up to **18.7x faster** on histogram rendering.
374
436
 
375
437
  Run the benchmark yourself:
376
438
  ```bash
439
+ maturin develop --release
377
440
  python tests/test_benchmark.py
378
441
  ```
379
442
 
@@ -445,25 +508,27 @@ Contributions are welcome! This is an open-source project under the MIT license.
445
508
  4. PRs require at least 1 review before merging
446
509
 
447
510
  **Project stats:**
448
- - **45+ Rust source files** — 23,000+ lines of native code
449
- - **25 Python modules** — 4,900+ lines of API
450
- - **47+ plot functions** (40 2D + 7 3D)
451
- - **70+ colormaps** (35 base + 35 reversed)
452
- - **298 tests** passing
453
- - **22 formatters + locators** (functional)
454
- - **Tk interactive backend** with navigation toolbar and event system
455
- - **Jupyter rich display** (`_repr_png_`, `_repr_svg_`, `_repr_html_`)
456
- - **Event system** with `mpl_connect` / `mpl_disconnect`
457
- - **RGB/RGBA imshow**, bilinear interpolation, heatmap annotations
458
- - **Signal processing**: specgram, psd, acorr, xcorr, coherence
511
+ - **53 Rust source files** — 30,000+ lines of native code
512
+ - **25+ Python modules** — thin PyO3 wrappers
513
+ - **50 plot types** (43 2D + 7 3D) — 100% of matplotlib plot types
514
+ - **81 colormaps** + reversed = ~162 total (~95% of matplotlib)
515
+ - **550+ tests** passing (including 27 rendering regression tests)
516
+ - **110/110 pyplot functions**, 95/95 Axes methods, 36/36 Figure methods
517
+ - **15 interpolation modes**: nearest, bilinear, bicubic, lanczos, spline16, hanning, hamming, hermite, kaiser, quadric, catrom, gaussian, bessel, mitchell, sinc
518
+ - **5 geographic projections**: Hammer, Aitoff, Mollweide, Lambert, Stereographic
519
+ - **4 backends**: Agg, Tk (interactive), Jupyter inline, WebAgg (browser)
520
+ - **4 output formats**: PNG, SVG, PDF (multi-page), EPS
521
+ - **Full TeX math engine**: Greek, sub/superscript, fractions, sqrt, matrices
522
+ - **Full transform system**: Affine2D, BlendedTransform, transData/transAxes
523
+ - **Full event system**: mouse, keyboard, pick events with Rust hit testing
524
+ - **Widgets**: Slider, Button, CheckButtons, RadioButtons, TextBox (Rust rendering)
525
+ - **Layout engines**: tight layout, constrained layout, GridSpec rowspan/colspan, SubFigure
459
526
  - **Zero `unsafe` blocks**
460
527
 
461
- **Priority areas for contribution:**
462
- - Qt/GTK backends
463
- - Functional widgets (Slider, Button, CheckButtons with real rendering)
464
- - 3D mouse rotation
465
- - Triangulation plots (tricontour, tripcolor)
466
- - LaTeX math rendering
528
+ **Remaining (need external dependencies):**
529
+ - Qt/GTK/macOS backends (need PyQt5, PyGObject, PyObjC)
530
+ - Math font rendering (need Computer Modern .ttf files)
531
+ - Basemap coastlines (need Natural Earth shapefiles)
467
532
 
468
533
  ---
469
534