rustplotlib 4.0.1__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 (151) hide show
  1. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/CLAUDE.md +18 -11
  2. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/Cargo.lock +1 -1
  3. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/Cargo.toml +1 -1
  4. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/PKG-INFO +136 -49
  5. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/README.md +134 -47
  6. rustplotlib-5.1.0/ROADMAP.md +220 -0
  7. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/pyproject.toml +2 -2
  8. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/python/rustplotlib/__init__.py +5 -3
  9. rustplotlib-5.1.0/python/rustplotlib/animation.py +221 -0
  10. rustplotlib-5.1.0/python/rustplotlib/backends/__init__.py +78 -0
  11. rustplotlib-5.1.0/python/rustplotlib/backends/backend_base.py +164 -0
  12. rustplotlib-5.1.0/python/rustplotlib/backends/backend_inline.py +70 -0
  13. rustplotlib-5.1.0/python/rustplotlib/backends/backend_pdf.py +152 -0
  14. rustplotlib-5.1.0/python/rustplotlib/backends/backend_tk.py +440 -0
  15. rustplotlib-5.1.0/python/rustplotlib/backends/backend_webagg.py +292 -0
  16. rustplotlib-5.1.0/python/rustplotlib/callback_registry.py +37 -0
  17. rustplotlib-5.1.0/python/rustplotlib/collections.py +112 -0
  18. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/python/rustplotlib/colors.py +65 -0
  19. rustplotlib-5.1.0/python/rustplotlib/dates.py +237 -0
  20. rustplotlib-5.1.0/python/rustplotlib/events.py +82 -0
  21. rustplotlib-5.1.0/python/rustplotlib/gridspec.py +75 -0
  22. rustplotlib-5.1.0/python/rustplotlib/mpl_toolkits/axes_grid1/__init__.py +5 -0
  23. rustplotlib-5.1.0/python/rustplotlib/mpl_toolkits/axes_grid1/axes_divider.py +89 -0
  24. rustplotlib-5.1.0/python/rustplotlib/patheffects.py +111 -0
  25. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/python/rustplotlib/pyplot.py +1655 -116
  26. rustplotlib-5.1.0/python/rustplotlib/pyplot.pyi +223 -0
  27. rustplotlib-5.1.0/python/rustplotlib/style/__init__.py +174 -0
  28. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/python/rustplotlib/ticker.py +17 -40
  29. rustplotlib-5.1.0/python/rustplotlib/transforms.py +166 -0
  30. rustplotlib-5.1.0/python/rustplotlib/widgets.py +399 -0
  31. rustplotlib-5.1.0/src/artists/colorbar_artist.rs +201 -0
  32. rustplotlib-5.1.0/src/artists/fancy_arrow.rs +319 -0
  33. rustplotlib-5.1.0/src/artists/image.rs +1775 -0
  34. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/src/artists/line2d.rs +158 -13
  35. rustplotlib-5.1.0/src/artists/line_collection.rs +113 -0
  36. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/src/artists/mod.rs +215 -0
  37. rustplotlib-5.1.0/src/artists/widget.rs +203 -0
  38. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/src/axes.rs +421 -72
  39. rustplotlib-5.1.0/src/colors.rs +285 -0
  40. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/src/figure.rs +754 -38
  41. rustplotlib-5.1.0/src/lib.rs +85 -0
  42. rustplotlib-5.1.0/src/mathtext.rs +703 -0
  43. rustplotlib-5.1.0/src/parse.rs +374 -0
  44. rustplotlib-5.1.0/src/projections.rs +240 -0
  45. rustplotlib-5.1.0/src/transforms.rs +245 -0
  46. rustplotlib-5.1.0/tests/test_advanced_customization.py +118 -0
  47. rustplotlib-5.1.0/tests/test_axes_figure_api.py +286 -0
  48. rustplotlib-5.1.0/tests/test_backend_tk.py +187 -0
  49. rustplotlib-5.1.0/tests/test_colorbar_annotations.py +148 -0
  50. rustplotlib-5.1.0/tests/test_colormaps.py +92 -0
  51. rustplotlib-5.1.0/tests/test_events.py +173 -0
  52. rustplotlib-5.1.0/tests/test_jupyter_repr.py +98 -0
  53. rustplotlib-5.1.0/tests/test_layout.py +137 -0
  54. rustplotlib-5.1.0/tests/test_markers.py +90 -0
  55. rustplotlib-5.1.0/tests/test_output_formats.py +88 -0
  56. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/tests/test_phase6_7.py +2 -1
  57. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/tests/test_phase8.py +17 -15
  58. rustplotlib-5.1.0/tests/test_polar.py +160 -0
  59. rustplotlib-5.1.0/tests/test_regression.py +204 -0
  60. rustplotlib-5.1.0/tests/test_spine_positioning.py +180 -0
  61. rustplotlib-5.1.0/tests/test_styles.py +121 -0
  62. rustplotlib-5.1.0/tests/test_triangulation.py +171 -0
  63. rustplotlib-5.1.0/tests/test_v5_features.py +744 -0
  64. rustplotlib-5.1.0/tests/test_widgets.py +259 -0
  65. rustplotlib-4.0.1/ROADMAP.md +0 -171
  66. rustplotlib-4.0.1/python/rustplotlib/animation.py +0 -94
  67. rustplotlib-4.0.1/python/rustplotlib/backends/__init__.py +0 -8
  68. rustplotlib-4.0.1/python/rustplotlib/backends/backend_inline.py +0 -24
  69. rustplotlib-4.0.1/python/rustplotlib/backends/backend_pdf.py +0 -56
  70. rustplotlib-4.0.1/python/rustplotlib/collections.py +0 -70
  71. rustplotlib-4.0.1/python/rustplotlib/dates.py +0 -87
  72. rustplotlib-4.0.1/python/rustplotlib/gridspec.py +0 -30
  73. rustplotlib-4.0.1/python/rustplotlib/patheffects.py +0 -36
  74. rustplotlib-4.0.1/python/rustplotlib/pyplot.pyi +0 -96
  75. rustplotlib-4.0.1/python/rustplotlib/style/__init__.py +0 -70
  76. rustplotlib-4.0.1/python/rustplotlib/transforms.py +0 -68
  77. rustplotlib-4.0.1/python/rustplotlib/widgets.py +0 -75
  78. rustplotlib-4.0.1/src/artists/image.rs +0 -757
  79. rustplotlib-4.0.1/src/colors.rs +0 -161
  80. rustplotlib-4.0.1/src/lib.rs +0 -47
  81. rustplotlib-4.0.1/src/transforms.rs +0 -104
  82. rustplotlib-4.0.1/tests/test_jupyter_repr.py +0 -15
  83. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/.github/workflows/ci.yml +0 -0
  84. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/.gitignore +0 -0
  85. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/CONTRIBUTING.md +0 -0
  86. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/LICENSE +0 -0
  87. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/benchmark_results.csv +0 -0
  88. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/dados/Data/PerfisTemp_rustplotlib.py +0 -0
  89. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/docs/superpowers/plans/2026-04-04-jupyter-and-event-foundation.md +0 -0
  90. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/python/rustplotlib/axes/__init__.py +0 -0
  91. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/python/rustplotlib/cm.py +0 -0
  92. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/python/rustplotlib/cycler.py +0 -0
  93. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/python/rustplotlib/figure.py +0 -0
  94. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/python/rustplotlib/font_manager.py +0 -0
  95. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/python/rustplotlib/lines.py +0 -0
  96. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/python/rustplotlib/mpl_toolkits/__init__.py +0 -0
  97. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/python/rustplotlib/mpl_toolkits/mplot3d/__init__.py +0 -0
  98. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/python/rustplotlib/patches.py +0 -0
  99. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/python/rustplotlib/spines.py +0 -0
  100. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/python/rustplotlib/text.py +0 -0
  101. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/src/artists/arrow.rs +0 -0
  102. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/src/artists/bar.rs +0 -0
  103. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/src/artists/bar3d.rs +0 -0
  104. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/src/artists/barh.rs +0 -0
  105. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/src/artists/boxplot.rs +0 -0
  106. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/src/artists/broken_barh.rs +0 -0
  107. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/src/artists/contour.rs +0 -0
  108. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/src/artists/contour3d.rs +0 -0
  109. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/src/artists/errorbar.rs +0 -0
  110. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/src/artists/eventplot.rs +0 -0
  111. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/src/artists/fill_between.rs +0 -0
  112. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/src/artists/fill_betweenx.rs +0 -0
  113. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/src/artists/fill_polygon.rs +0 -0
  114. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/src/artists/hexbin.rs +0 -0
  115. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/src/artists/hist.rs +0 -0
  116. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/src/artists/legend.rs +0 -0
  117. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/src/artists/line3d.rs +0 -0
  118. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/src/artists/patches.rs +0 -0
  119. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/src/artists/pcolormesh.rs +0 -0
  120. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/src/artists/pie.rs +0 -0
  121. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/src/artists/quiver.rs +0 -0
  122. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/src/artists/radar.rs +0 -0
  123. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/src/artists/sankey.rs +0 -0
  124. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/src/artists/scatter.rs +0 -0
  125. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/src/artists/scatter3d.rs +0 -0
  126. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/src/artists/stem.rs +0 -0
  127. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/src/artists/step.rs +0 -0
  128. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/src/artists/streamplot.rs +0 -0
  129. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/src/artists/surface3d.rs +0 -0
  130. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/src/artists/trisurf3d.rs +0 -0
  131. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/src/artists/violin.rs +0 -0
  132. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/src/artists/wireframe3d.rs +0 -0
  133. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/src/axes3d.rs +0 -0
  134. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/src/fonts/DejaVuSans.ttf +0 -0
  135. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/src/projection3d.rs +0 -0
  136. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/src/svg_renderer.rs +0 -0
  137. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/src/text.rs +0 -0
  138. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/src/ticker.rs +0 -0
  139. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/src/window.rs +0 -0
  140. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/tests/test_3d.py +0 -0
  141. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/tests/test_benchmark.py +0 -0
  142. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/tests/test_colors.py +0 -0
  143. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/tests/test_figure.py +0 -0
  144. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/tests/test_new_features.py +0 -0
  145. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/tests/test_new_features2.py +0 -0
  146. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/tests/test_phase9_features.py +0 -0
  147. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/tests/test_pyplot.py +0 -0
  148. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/tests/test_spectral_features.py +0 -0
  149. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/tests/test_ticker.py +0 -0
  150. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/tests/test_transforms.py +0 -0
  151. {rustplotlib-4.0.1 → rustplotlib-5.1.0}/tests/test_v3_features.py +0 -0
@@ -6,14 +6,19 @@ Reimplementação completa do matplotlib em Rust puro. Drop-in replacement via P
6
6
 
7
7
  - Sempre responder em português (pt-BR)
8
8
 
9
- ## Estado Atual — v4.0.0
9
+ ## Estado Atual — v5.0.0 (Phase 1 + Phase 2)
10
10
 
11
11
  - 40+ plot types 2D, 7 plot types 3D
12
12
  - 70+ colormaps (35 base + 35 reversed)
13
- - 21 módulos Python compatíveis com API matplotlib
14
- - 267 testes passando
13
+ - 25 módulos Python compatíveis com API matplotlib
14
+ - 550+ testes passando
15
+ - Tk backend interativo com toolbar, zoom/pan funcional, pixel-to-data mapping
16
+ - Jupyter rich display (`_repr_png_`, `_repr_svg_`, `_repr_html_`)
17
+ - Sistema de eventos com `CallbackRegistry` e `mpl_connect`/`mpl_disconnect`
18
+ - Widgets funcionais: Slider, Button, CheckButtons, RadioButtons, TextBox, RangeSlider
19
+ - Backend auto-detection (inline/tk/agg)
15
20
  - Output: PNG (tiny-skia), SVG nativo, PDF, GIF, janela interativa
16
- - Performance: até 30x mais rápido que matplotlib
21
+ - Performance: até 16x mais rápido que matplotlib (benchmark real com 12 testes)
17
22
  - Zero blocos `unsafe` em todo o código Rust
18
23
 
19
24
  ## Estrutura do Projeto
@@ -41,10 +46,13 @@ python/rustplotlib/ # Camada Python
41
46
  ├── style/ # Temas (dark_background, ggplot, seaborn, bmh, fivethirtyeight)
42
47
  ├── animation.py # FuncAnimation + GIF
43
48
  ├── ticker.py # 12 Formatters + 10 Locators funcionais
49
+ ├── backends/ # backend_base, backend_inline, backend_tk, backend_pdf
50
+ ├── events.py # MouseEvent, KeyEvent, DrawEvent, ResizeEvent, CloseEvent
51
+ ├── callback_registry.py # CallbackRegistry (mpl_connect/mpl_disconnect)
44
52
  ├── dates.py, colors.py, patches.py, ...
45
53
  └── mpl_toolkits/mplot3d/ # Suporte 3D
46
54
 
47
- tests/ # Testes Python (267 testes)
55
+ tests/ # Testes Python (326 testes)
48
56
  ```
49
57
 
50
58
  ## Stack Técnica
@@ -95,15 +103,14 @@ cargo check # Verificar compilação Rust
95
103
  - **Manter compatibilidade com API do matplotlib** — mesmos nomes de funções e parâmetros
96
104
  - **Atualizar ROADMAP.md e README.md** ao completar features
97
105
 
98
- ## Roadmap Ativo (próximo: v5.0.0)
106
+ ## Roadmap Ativo (próximo: v5.1.0)
99
107
 
100
108
  Próximos itens prioritários (ver ROADMAP.md para lista completa):
101
109
 
102
- 1. **Jupyter inline backend** — rich display protocol, _repr_png_
103
- 2. **Backends interativos** — Qt, GTK, macOS native
104
- 3. **Widgets funcionais** — Slider, Button, CheckButtons com renderização real
105
- 4. **Features interativas** — mouse events, zoom/pan, rotação 3D
106
- 5. **Triangulation plots** — tricontour, tricontourf, tripcolor (atualmente stubs)
110
+ 1. **Backends adicionais** — Qt, GTK, WebAgg, macOS native
111
+ 2. **Features interativas** — pick events, rotação 3D, blitting
112
+ 4. **Triangulation plots** — tricontour, tricontourf, tripcolor (atualmente stubs)
113
+ 5. **Customização avançada** — spine positioning, TwoSlopeNorm, interpolação bicúbica
107
114
 
108
115
  ## Git
109
116
 
@@ -1368,7 +1368,7 @@ dependencies = [
1368
1368
 
1369
1369
  [[package]]
1370
1370
  name = "rustplotlib"
1371
- version = "4.0.1"
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 = "4.0.1"
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: 4.0.1
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,48 +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 display |
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 |
207
+
208
+ ### Backends & Interactive
209
+ | Feature | Description |
210
+ |---|---|
211
+ | Backend auto-detection | Automatically selects inline (Jupyter), Tk, or Agg backend |
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) |
215
+ | Event system | `mpl_connect` / `mpl_disconnect` with `CallbackRegistry` |
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 |
218
+ | Jupyter rich display | `_repr_png_()`, `_repr_svg_()`, `_repr_html_()` on Figure |
219
+ | 3D mouse rotation | Drag to rotate 3D view in Tk backend |
203
220
 
204
221
  ### Animation
205
222
  | Feature | Description |
206
223
  |---|---|
207
- | `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 |
208
226
  | GIF export | Save animations as GIF (via Pillow) |
209
- | 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 |
210
259
 
211
260
  ### Styles & Themes
212
261
  | Feature | Description |
213
262
  |---|---|
214
- | `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 |
215
266
  | `rcParams` | Functional global configuration (30+ supported keys) |
216
267
  | `set_facecolor()` | Figure and axes background colors |
217
268
 
218
269
  ### Colors
219
- - **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.)
220
271
  - **Shorthand:** `"r"`, `"g"`, `"b"`, `"c"`, `"m"`, `"y"`, `"k"`, `"w"`
221
272
  - **Hex:** `"#FF0000"`, `"#f00"`, `"#FF000080"`
222
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
223
275
 
224
276
  ### Linestyles & Markers
225
277
  - **Linestyles:** `-` (solid), `--` (dashed), `-.` (dashdot), `:` (dotted)
226
- - **Markers:** `.` `o` `s` `^` `v` `+` `x` `D` `*`
227
- - **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)
228
280
  - **markevery:** show marker every N points
229
281
 
230
- ### Colormaps (70+)
231
- 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`
232
284
 
233
- `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.
234
286
 
235
- 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`
236
289
 
237
- ### Text Rendering
290
+ ### Text & Math Rendering
238
291
  - Embedded DejaVu Sans font (no system font dependency)
239
- - 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.
240
313
 
241
314
  ### Data Integration
242
315
  - **Pandas:** plot directly from DataFrame/Series (optional dependency)
@@ -245,20 +318,22 @@ All also available as `viridis_r`, `plasma_r`, `hot_r`, etc.
245
318
  - **Dates:** `date2num()`, `num2date()`, date formatters and locators
246
319
  - **Categorical axes:** string-based x values automatically converted
247
320
 
248
- ### Compatibility Modules (21 modules)
321
+ ### Compatibility Modules (25 modules)
249
322
  | Module | Status |
250
323
  |---|---|
251
324
  | `rustplotlib.pyplot` | Full implementation (50+ functions) |
252
325
  | `rustplotlib.style` | Full implementation (6 themes) |
253
326
  | `rustplotlib.animation` | FuncAnimation + GIF export |
254
- | `rustplotlib.widgets` | Stubs (Slider, Button, CheckButtons, RadioButtons, TextBox, Cursor) |
327
+ | `rustplotlib.widgets` | Functional (Slider, Button, CheckButtons, RadioButtons, TextBox, RangeSlider, Cursor) |
255
328
  | `rustplotlib.font_manager` | FontProperties |
256
329
  | `rustplotlib.ticker` | 12 Formatters + 10 Locators (functional) |
257
330
  | `rustplotlib.patches` | Rectangle, Circle, Polygon, FancyBboxPatch, Wedge, FancyArrowPatch |
258
331
  | `rustplotlib.colors` | LinearSegmentedColormap, Normalize, LogNorm, BoundaryNorm |
259
332
  | `rustplotlib.dates` | Date conversion, DateFormatter, DateLocator, Auto/Day/Month/Year/Hour/MinuteLocator |
260
333
  | `rustplotlib.gridspec` | GridSpec, SubplotSpec |
261
- | `rustplotlib.backends` | Backend system, PdfPages |
334
+ | `rustplotlib.backends` | Backend system with auto-detection (inline/tk/agg), PdfPages |
335
+ | `rustplotlib.backends.backend_base` | FigureCanvasBase, FigureManagerBase, NavigationToolbar2 |
336
+ | `rustplotlib.backends.backend_tk` | Tk interactive window with toolbar and events |
262
337
  | `rustplotlib.mpl_toolkits.mplot3d` | Axes3D for 3D plotting |
263
338
  | `rustplotlib.cm` | Colormap access by name |
264
339
  | `rustplotlib.collections` | LineCollection, PathCollection, PatchCollection |
@@ -267,7 +342,10 @@ All also available as `viridis_r`, `plasma_r`, `hot_r`, etc.
267
342
  | `rustplotlib.transforms` | Bbox, Affine2D, BboxTransform |
268
343
  | `rustplotlib.patheffects` | Stroke, withStroke, SimplePatchShadow |
269
344
  | `rustplotlib.spines` | Spine |
270
- | `rustplotlib.figure` | Figure class reference |
345
+ | `rustplotlib.axes` | Axes class reference |
346
+ | `rustplotlib.figure` | Figure class with Jupyter rich display (`_repr_png_`, `_repr_svg_`, `_repr_html_`) |
347
+ | `rustplotlib.events` | MouseEvent, KeyEvent, DrawEvent, ResizeEvent, CloseEvent |
348
+ | `rustplotlib.callback_registry` | CallbackRegistry for mpl_connect/mpl_disconnect |
271
349
  | `rustplotlib.cycler` | cycler compatibility |
272
350
 
273
351
  ---
@@ -356,25 +434,29 @@ anim.save("wave.gif")
356
434
 
357
435
  ## Performance Benchmark
358
436
 
359
- 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:
360
438
 
361
439
  | Benchmark | matplotlib | rustplotlib | Speedup |
362
440
  |---|---|---|---|
363
- | Line Plot (10k pts) | 0.028s | 0.005s | **5.3x** |
364
- | Scatter (5k pts) | 0.028s | 0.021s | **1.4x** |
365
- | Bar Chart (50 bars) | 0.026s | 0.005s | **5.0x** |
366
- | Histogram (100k pts) | 0.090s | 0.006s | **16.1x** |
367
- | Subplots 2x2 | 0.046s | 0.011s | **4.2x** |
368
- | Heatmap (100x100) | 0.021s | 0.006s | **3.4x** |
369
- | Large Line (100k pts) | 0.110s | 0.109s | **1.0x** |
370
- | Multi-line (20 lines) | 0.090s | 0.037s | **2.4x** |
371
- | Error Bars | 0.022s | 0.004s | **6.4x** |
372
- | Pie Chart | 0.012s | 0.005s | **2.7x** |
373
- | SVG Output | 0.021s | 0.003s | **6.9x** |
374
- | 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.
375
456
 
376
457
  Run the benchmark yourself:
377
458
  ```bash
459
+ maturin develop --release
378
460
  python tests/test_benchmark.py
379
461
  ```
380
462
 
@@ -446,22 +528,27 @@ Contributions are welcome! This is an open-source project under the MIT license.
446
528
  4. PRs require at least 1 review before merging
447
529
 
448
530
  **Project stats:**
449
- - **45+ Rust source files** — 23,000+ lines of native code
450
- - **21 Python modules** — 8,000+ lines of API
451
- - **47+ plot functions** (40 2D + 7 3D)
452
- - **70+ colormaps** (35 base + 35 reversed)
453
- - **267 tests** passing
454
- - **22 formatters + locators** (functional)
455
- - **RGB/RGBA imshow**, bilinear interpolation, heatmap annotations
456
- - **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
457
546
  - **Zero `unsafe` blocks**
458
547
 
459
- **Priority areas for contribution:**
460
- - Jupyter inline backend (rich display protocol)
461
- - Functional widgets (Slider, Button, CheckButtons with real rendering)
462
- - Interactive features (mouse events, zoom/pan, 3D rotation)
463
- - Qt/GTK backends
464
- - Triangulation plots (tricontour, tripcolor)
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)
465
552
 
466
553
  ---
467
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,48 +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 display |
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 |
187
+
188
+ ### Backends & Interactive
189
+ | Feature | Description |
190
+ |---|---|
191
+ | Backend auto-detection | Automatically selects inline (Jupyter), Tk, or Agg backend |
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) |
195
+ | Event system | `mpl_connect` / `mpl_disconnect` with `CallbackRegistry` |
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 |
198
+ | Jupyter rich display | `_repr_png_()`, `_repr_svg_()`, `_repr_html_()` on Figure |
199
+ | 3D mouse rotation | Drag to rotate 3D view in Tk backend |
183
200
 
184
201
  ### Animation
185
202
  | Feature | Description |
186
203
  |---|---|
187
- | `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 |
188
206
  | GIF export | Save animations as GIF (via Pillow) |
189
- | 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 |
190
239
 
191
240
  ### Styles & Themes
192
241
  | Feature | Description |
193
242
  |---|---|
194
- | `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 |
195
246
  | `rcParams` | Functional global configuration (30+ supported keys) |
196
247
  | `set_facecolor()` | Figure and axes background colors |
197
248
 
198
249
  ### Colors
199
- - **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.)
200
251
  - **Shorthand:** `"r"`, `"g"`, `"b"`, `"c"`, `"m"`, `"y"`, `"k"`, `"w"`
201
252
  - **Hex:** `"#FF0000"`, `"#f00"`, `"#FF000080"`
202
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
203
255
 
204
256
  ### Linestyles & Markers
205
257
  - **Linestyles:** `-` (solid), `--` (dashed), `-.` (dashdot), `:` (dotted)
206
- - **Markers:** `.` `o` `s` `^` `v` `+` `x` `D` `*`
207
- - **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)
208
260
  - **markevery:** show marker every N points
209
261
 
210
- ### Colormaps (70+)
211
- 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`
212
264
 
213
- `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.
214
266
 
215
- 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`
216
269
 
217
- ### Text Rendering
270
+ ### Text & Math Rendering
218
271
  - Embedded DejaVu Sans font (no system font dependency)
219
- - 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.
220
293
 
221
294
  ### Data Integration
222
295
  - **Pandas:** plot directly from DataFrame/Series (optional dependency)
@@ -225,20 +298,22 @@ All also available as `viridis_r`, `plasma_r`, `hot_r`, etc.
225
298
  - **Dates:** `date2num()`, `num2date()`, date formatters and locators
226
299
  - **Categorical axes:** string-based x values automatically converted
227
300
 
228
- ### Compatibility Modules (21 modules)
301
+ ### Compatibility Modules (25 modules)
229
302
  | Module | Status |
230
303
  |---|---|
231
304
  | `rustplotlib.pyplot` | Full implementation (50+ functions) |
232
305
  | `rustplotlib.style` | Full implementation (6 themes) |
233
306
  | `rustplotlib.animation` | FuncAnimation + GIF export |
234
- | `rustplotlib.widgets` | Stubs (Slider, Button, CheckButtons, RadioButtons, TextBox, Cursor) |
307
+ | `rustplotlib.widgets` | Functional (Slider, Button, CheckButtons, RadioButtons, TextBox, RangeSlider, Cursor) |
235
308
  | `rustplotlib.font_manager` | FontProperties |
236
309
  | `rustplotlib.ticker` | 12 Formatters + 10 Locators (functional) |
237
310
  | `rustplotlib.patches` | Rectangle, Circle, Polygon, FancyBboxPatch, Wedge, FancyArrowPatch |
238
311
  | `rustplotlib.colors` | LinearSegmentedColormap, Normalize, LogNorm, BoundaryNorm |
239
312
  | `rustplotlib.dates` | Date conversion, DateFormatter, DateLocator, Auto/Day/Month/Year/Hour/MinuteLocator |
240
313
  | `rustplotlib.gridspec` | GridSpec, SubplotSpec |
241
- | `rustplotlib.backends` | Backend system, PdfPages |
314
+ | `rustplotlib.backends` | Backend system with auto-detection (inline/tk/agg), PdfPages |
315
+ | `rustplotlib.backends.backend_base` | FigureCanvasBase, FigureManagerBase, NavigationToolbar2 |
316
+ | `rustplotlib.backends.backend_tk` | Tk interactive window with toolbar and events |
242
317
  | `rustplotlib.mpl_toolkits.mplot3d` | Axes3D for 3D plotting |
243
318
  | `rustplotlib.cm` | Colormap access by name |
244
319
  | `rustplotlib.collections` | LineCollection, PathCollection, PatchCollection |
@@ -247,7 +322,10 @@ All also available as `viridis_r`, `plasma_r`, `hot_r`, etc.
247
322
  | `rustplotlib.transforms` | Bbox, Affine2D, BboxTransform |
248
323
  | `rustplotlib.patheffects` | Stroke, withStroke, SimplePatchShadow |
249
324
  | `rustplotlib.spines` | Spine |
250
- | `rustplotlib.figure` | Figure class reference |
325
+ | `rustplotlib.axes` | Axes class reference |
326
+ | `rustplotlib.figure` | Figure class with Jupyter rich display (`_repr_png_`, `_repr_svg_`, `_repr_html_`) |
327
+ | `rustplotlib.events` | MouseEvent, KeyEvent, DrawEvent, ResizeEvent, CloseEvent |
328
+ | `rustplotlib.callback_registry` | CallbackRegistry for mpl_connect/mpl_disconnect |
251
329
  | `rustplotlib.cycler` | cycler compatibility |
252
330
 
253
331
  ---
@@ -336,25 +414,29 @@ anim.save("wave.gif")
336
414
 
337
415
  ## Performance Benchmark
338
416
 
339
- 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:
340
418
 
341
419
  | Benchmark | matplotlib | rustplotlib | Speedup |
342
420
  |---|---|---|---|
343
- | Line Plot (10k pts) | 0.028s | 0.005s | **5.3x** |
344
- | Scatter (5k pts) | 0.028s | 0.021s | **1.4x** |
345
- | Bar Chart (50 bars) | 0.026s | 0.005s | **5.0x** |
346
- | Histogram (100k pts) | 0.090s | 0.006s | **16.1x** |
347
- | Subplots 2x2 | 0.046s | 0.011s | **4.2x** |
348
- | Heatmap (100x100) | 0.021s | 0.006s | **3.4x** |
349
- | Large Line (100k pts) | 0.110s | 0.109s | **1.0x** |
350
- | Multi-line (20 lines) | 0.090s | 0.037s | **2.4x** |
351
- | Error Bars | 0.022s | 0.004s | **6.4x** |
352
- | Pie Chart | 0.012s | 0.005s | **2.7x** |
353
- | SVG Output | 0.021s | 0.003s | **6.9x** |
354
- | 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.
355
436
 
356
437
  Run the benchmark yourself:
357
438
  ```bash
439
+ maturin develop --release
358
440
  python tests/test_benchmark.py
359
441
  ```
360
442
 
@@ -426,22 +508,27 @@ Contributions are welcome! This is an open-source project under the MIT license.
426
508
  4. PRs require at least 1 review before merging
427
509
 
428
510
  **Project stats:**
429
- - **45+ Rust source files** — 23,000+ lines of native code
430
- - **21 Python modules** — 8,000+ lines of API
431
- - **47+ plot functions** (40 2D + 7 3D)
432
- - **70+ colormaps** (35 base + 35 reversed)
433
- - **267 tests** passing
434
- - **22 formatters + locators** (functional)
435
- - **RGB/RGBA imshow**, bilinear interpolation, heatmap annotations
436
- - **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
437
526
  - **Zero `unsafe` blocks**
438
527
 
439
- **Priority areas for contribution:**
440
- - Jupyter inline backend (rich display protocol)
441
- - Functional widgets (Slider, Button, CheckButtons with real rendering)
442
- - Interactive features (mouse events, zoom/pan, 3D rotation)
443
- - Qt/GTK backends
444
- - Triangulation plots (tricontour, tripcolor)
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)
445
532
 
446
533
  ---
447
534