anyplotlib 0.8.0__tar.gz → 0.9.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 (298) hide show
  1. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/AGENTS.md +3 -3
  2. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/CHANGELOG.rst +116 -0
  3. anyplotlib-0.9.0/Examples/PlotTypes/plot_aspect_ratio.py +77 -0
  4. anyplotlib-0.9.0/Examples/PlotTypes/plot_subplots_adjust.py +90 -0
  5. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/PKG-INFO +1 -1
  6. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/FIGURE_ESM.md +423 -85
  7. anyplotlib-0.9.0/anyplotlib/_export.py +262 -0
  8. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/_repr_utils.py +70 -33
  9. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/_utils.py +14 -0
  10. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/axes/_axes.py +8 -2
  11. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/callbacks.py +4 -0
  12. anyplotlib-0.9.0/anyplotlib/embed.py +457 -0
  13. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/figure/_figure.py +109 -0
  14. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/figure_esm.js +2172 -80
  15. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/plot2d/_plot2d.py +149 -5
  16. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/plot2d/_plotmesh.py +11 -1
  17. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/plot2d/_tile_backend.py +45 -16
  18. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/sphinx_anywidget/_scraper.py +13 -52
  19. anyplotlib-0.9.0/anyplotlib/tests/test_embed/_export_utils.py +71 -0
  20. anyplotlib-0.9.0/anyplotlib/tests/test_embed/conftest.py +80 -0
  21. anyplotlib-0.9.0/anyplotlib/tests/test_embed/test_embed_3d.py +328 -0
  22. anyplotlib-0.9.0/anyplotlib/tests/test_embed/test_embed_api.py +269 -0
  23. anyplotlib-0.9.0/anyplotlib/tests/test_embed/test_embed_escaping.py +139 -0
  24. anyplotlib-0.9.0/anyplotlib/tests/test_embed/test_embed_navigated.py +906 -0
  25. anyplotlib-0.9.0/anyplotlib/tests/test_embed/test_embed_set_image.py +306 -0
  26. anyplotlib-0.9.0/anyplotlib/tests/test_embed/test_export_menu.py +523 -0
  27. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_embed/test_export_png.py +14 -80
  28. anyplotlib-0.9.0/anyplotlib/tests/test_embed/test_export_sources.py +386 -0
  29. anyplotlib-0.9.0/anyplotlib/tests/test_embed/test_savefig.py +290 -0
  30. anyplotlib-0.9.0/anyplotlib/tests/test_plot2d/test_status_pixel_value.py +730 -0
  31. anyplotlib-0.9.0/anyplotlib/tests/test_plot2d/test_tile_backend.py +199 -0
  32. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/docs/_root/index.html +3 -3
  33. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/docs/_root/switcher.json +5 -0
  34. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/docs/conf.py +1 -1
  35. anyplotlib-0.9.0/docs/embedding.rst +444 -0
  36. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/docs/events.rst +88 -0
  37. anyplotlib-0.9.0/docs/exporting.rst +218 -0
  38. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/docs/index.rst +12 -0
  39. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/pyproject.toml +1 -1
  40. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/uv.lock +1 -1
  41. anyplotlib-0.8.0/anyplotlib/embed.py +0 -194
  42. anyplotlib-0.8.0/anyplotlib/tests/test_embed/test_embed_api.py +0 -133
  43. anyplotlib-0.8.0/anyplotlib/tests/test_plot2d/test_tile_backend.py +0 -99
  44. anyplotlib-0.8.0/docs/embedding.rst +0 -181
  45. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/.github/workflows/ci.yml +0 -0
  46. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/.github/workflows/docs.yml +0 -0
  47. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/.github/workflows/prepare_release.yml +0 -0
  48. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/.github/workflows/release.yml +0 -0
  49. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/.github/workflows/tests.yml +0 -0
  50. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/.gitignore +0 -0
  51. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/Examples/Benchmarks/README.rst +0 -0
  52. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/Examples/Benchmarks/plot_benchmark_comparison.py +0 -0
  53. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/Examples/Interactive/README.rst +0 -0
  54. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/Examples/Interactive/plot_3d_spectral_viewer.py +0 -0
  55. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/Examples/Interactive/plot_eels_explorer.py +0 -0
  56. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/Examples/Interactive/plot_figure_annotations.py +0 -0
  57. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/Examples/Interactive/plot_interactive_fft.py +0 -0
  58. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/Examples/Interactive/plot_interactive_fitting.py +0 -0
  59. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/Examples/Interactive/plot_ipf_density_map.py +0 -0
  60. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/Examples/Interactive/plot_ipf_explorer.py +0 -0
  61. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/Examples/Interactive/plot_key_bindings.py +0 -0
  62. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/Examples/Interactive/plot_particle_picker.py +0 -0
  63. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/Examples/Interactive/plot_point_widget.py +0 -0
  64. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/Examples/Interactive/plot_segment_by_contrast.py +0 -0
  65. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/Examples/Interactive/plot_segment_by_contrast_advanced.py +0 -0
  66. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/Examples/Interactive/plot_spectra_roi_inspector.py +0 -0
  67. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/Examples/Interactive/plot_star_globe_explorer.py +0 -0
  68. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/Examples/Interactive/plot_threshold_explorer.py +0 -0
  69. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/Examples/Interactive/plot_voxel_grain_explorer.py +0 -0
  70. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/Examples/Markers/README.rst +0 -0
  71. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/Examples/Markers/plot_arrows.py +0 -0
  72. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/Examples/Markers/plot_circles.py +0 -0
  73. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/Examples/Markers/plot_ellipses.py +0 -0
  74. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/Examples/Markers/plot_horizontal_lines.py +0 -0
  75. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/Examples/Markers/plot_line_segments.py +0 -0
  76. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/Examples/Markers/plot_points.py +0 -0
  77. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/Examples/Markers/plot_polygons.py +0 -0
  78. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/Examples/Markers/plot_rectangles.py +0 -0
  79. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/Examples/Markers/plot_squares.py +0 -0
  80. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/Examples/Markers/plot_texts.py +0 -0
  81. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/Examples/Markers/plot_transform_markers.py +0 -0
  82. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/Examples/Markers/plot_vertical_lines.py +0 -0
  83. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/Examples/PlotTypes/README.rst +0 -0
  84. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/Examples/PlotTypes/plot_3d.py +0 -0
  85. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/Examples/PlotTypes/plot_3d_texture.py +0 -0
  86. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/Examples/PlotTypes/plot_bar.py +0 -0
  87. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/Examples/PlotTypes/plot_gpu_voxels.py +0 -0
  88. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/Examples/PlotTypes/plot_gridspec_custom.py +0 -0
  89. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/Examples/PlotTypes/plot_image2d.py +0 -0
  90. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/Examples/PlotTypes/plot_inset.py +0 -0
  91. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/Examples/PlotTypes/plot_key_overlays.py +0 -0
  92. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/Examples/PlotTypes/plot_label_formatting.py +0 -0
  93. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/Examples/PlotTypes/plot_line_styles.py +0 -0
  94. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/Examples/PlotTypes/plot_pcolormesh.py +0 -0
  95. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/Examples/PlotTypes/plot_spectra1d.py +0 -0
  96. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/Examples/PlotTypes/plot_step_and_log.py +0 -0
  97. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/Examples/PlotTypes/plot_tile_backend.py +0 -0
  98. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/Examples/PlotTypes/plot_twinx.py +0 -0
  99. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/Examples/README.rst +0 -0
  100. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/Examples/Widgets/README.rst +0 -0
  101. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/Examples/Widgets/plot_widget1d_hline.py +0 -0
  102. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/Examples/Widgets/plot_widget1d_point.py +0 -0
  103. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/Examples/Widgets/plot_widget1d_range.py +0 -0
  104. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/Examples/Widgets/plot_widget1d_vline.py +0 -0
  105. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/Examples/Widgets/plot_widget2d_annular.py +0 -0
  106. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/Examples/Widgets/plot_widget2d_arrow.py +0 -0
  107. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/Examples/Widgets/plot_widget2d_circle.py +0 -0
  108. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/Examples/Widgets/plot_widget2d_crosshair.py +0 -0
  109. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/Examples/Widgets/plot_widget2d_label.py +0 -0
  110. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/Examples/Widgets/plot_widget2d_polygon.py +0 -0
  111. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/Examples/Widgets/plot_widget2d_rectangle.py +0 -0
  112. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/Examples/Widgets/plot_widget3d_plane.py +0 -0
  113. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/LICENSE +0 -0
  114. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/Makefile +0 -0
  115. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/README.md +0 -0
  116. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/__init__.py +0 -0
  117. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/_base_plot.py +0 -0
  118. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/_binary_frame.py +0 -0
  119. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/_electron.py +0 -0
  120. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/axes/__init__.py +0 -0
  121. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/axes/_inset_axes.py +0 -0
  122. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/conftest.py +0 -0
  123. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/figure/__init__.py +0 -0
  124. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/figure/_gridspec.py +0 -0
  125. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/figure/_subplots.py +0 -0
  126. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/keys.py +0 -0
  127. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/markers.py +0 -0
  128. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/plot1d/__init__.py +0 -0
  129. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/plot1d/_plot1d.py +0 -0
  130. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/plot1d/_plotbar.py +0 -0
  131. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/plot2d/__init__.py +0 -0
  132. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/plot2d/_layer.py +0 -0
  133. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/plot3d/__init__.py +0 -0
  134. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/plot3d/_plot3d.py +0 -0
  135. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/plotxy/__init__.py +0 -0
  136. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/plotxy/_plotxy.py +0 -0
  137. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/sphinx_anywidget/__init__.py +0 -0
  138. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/sphinx_anywidget/_directive.py +0 -0
  139. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/sphinx_anywidget/_repr_utils.py +0 -0
  140. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/sphinx_anywidget/_wheel_builder.py +0 -0
  141. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/sphinx_anywidget/static/anywidget_bridge.js +0 -0
  142. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/sphinx_anywidget/static/anywidget_overlay.css +0 -0
  143. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/sphinx_anywidget/tests/__init__.py +0 -0
  144. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/sphinx_anywidget/tests/conftest.py +0 -0
  145. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/sphinx_anywidget/tests/test_directive.py +0 -0
  146. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/sphinx_anywidget/tests/test_init.py +0 -0
  147. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/sphinx_anywidget/tests/test_repr_utils.py +0 -0
  148. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/sphinx_anywidget/tests/test_scraper.py +0 -0
  149. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/sphinx_anywidget/tests/test_wheel_builder.py +0 -0
  150. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/__init__.py +0 -0
  151. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/_gpu_clim_check.cjs +0 -0
  152. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/_png_utils.py +0 -0
  153. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/baselines/bar_basic.png +0 -0
  154. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/baselines/gridspec_3col_equal_spectra.png +0 -0
  155. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/baselines/gridspec_asymmetric_width_ratios.png +0 -0
  156. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/baselines/gridspec_height_ratio_image_histogram.png +0 -0
  157. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/baselines/gridspec_image_two_spectra.png +0 -0
  158. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/baselines/gridspec_side_by_side_1d.png +0 -0
  159. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/baselines/gridspec_spanning_top_two_bottom.png +0 -0
  160. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/baselines/imshow_axis_off.png +0 -0
  161. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/baselines/imshow_checkerboard.png +0 -0
  162. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/baselines/imshow_gradient.png +0 -0
  163. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/baselines/imshow_labels.png +0 -0
  164. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/baselines/imshow_viridis.png +0 -0
  165. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/baselines/inset_1d.png +0 -0
  166. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/baselines/inset_maximized.png +0 -0
  167. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/baselines/inset_minimized.png +0 -0
  168. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/baselines/inset_normal_2d.png +0 -0
  169. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/baselines/inset_stacked.png +0 -0
  170. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/baselines/inset_stacked_one_minimized.png +0 -0
  171. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/baselines/pcolormesh_uniform.png +0 -0
  172. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/baselines/plot1d_all_linestyles.png +0 -0
  173. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/baselines/plot1d_alpha.png +0 -0
  174. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/baselines/plot1d_axis_off.png +0 -0
  175. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/baselines/plot1d_dashed.png +0 -0
  176. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/baselines/plot1d_marker_symbols.png +0 -0
  177. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/baselines/plot1d_markers.png +0 -0
  178. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/baselines/plot1d_multi.png +0 -0
  179. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/baselines/plot1d_sine.png +0 -0
  180. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/baselines/plot1d_title.png +0 -0
  181. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/baselines/plot1d_twinx.png +0 -0
  182. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/baselines/plot3d_surface.png +0 -0
  183. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/baselines/subplots_2x1.png +0 -0
  184. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/conftest.py +0 -0
  185. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_benchmarks/__init__.py +0 -0
  186. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_benchmarks/baselines.json +0 -0
  187. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_benchmarks/benchmarks/baselines.json +0 -0
  188. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_benchmarks/test_benchmarks.py +0 -0
  189. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_benchmarks/test_benchmarks_py.py +0 -0
  190. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_documentation/__init__.py +0 -0
  191. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_documentation/test_bridge.py +0 -0
  192. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_documentation/test_push_hook.py +0 -0
  193. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_documentation/test_scraper.py +0 -0
  194. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_electron/__init__.py +0 -0
  195. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_electron/test_binary_frame.py +0 -0
  196. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_embed/__init__.py +0 -0
  197. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_embed/test_embed_mount.py +0 -0
  198. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_embed/test_export_pixel_tokens.py +0 -0
  199. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_embed/test_export_widget_sync.py +0 -0
  200. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_examples/__init__.py +0 -0
  201. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_examples/test_interactive_examples.py +0 -0
  202. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_interactive/__init__.py +0 -0
  203. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_interactive/_event_test_utils.py +0 -0
  204. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_interactive/test_blit_audit.py +0 -0
  205. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_interactive/test_callbacks_playwright.py +0 -0
  206. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_interactive/test_callbacks_unit.py +0 -0
  207. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_interactive/test_circle_lock_center.py +0 -0
  208. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_interactive/test_edit_chrome.py +0 -0
  209. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_interactive/test_edit_chrome_playwright.py +0 -0
  210. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_interactive/test_event_pause_hold.py +0 -0
  211. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_interactive/test_event_plots.py +0 -0
  212. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_interactive/test_event_settled.py +0 -0
  213. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_interactive/test_events_regression.py +0 -0
  214. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_interactive/test_orbit_direction.py +0 -0
  215. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_interactive/test_pointer_down_1d.py +0 -0
  216. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_interactive/test_range_orientation_snap.py +0 -0
  217. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_interactive/test_star_globe_linking.py +0 -0
  218. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_interactive/test_tile_parity_playwright.py +0 -0
  219. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_interactive/test_title.py +0 -0
  220. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_interactive/test_touch.py +0 -0
  221. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_interactive/test_widget_brush.py +0 -0
  222. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_interactive/test_widget_max_extent.py +0 -0
  223. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_interactive/test_widget_set_notify.py +0 -0
  224. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_interactive/test_widgets.py +0 -0
  225. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_interactive/test_widgets_line_2d.py +0 -0
  226. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_keys/test_keys.py +0 -0
  227. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_labels/__init__.py +0 -0
  228. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_labels/test_label_api.py +0 -0
  229. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_labels/test_label_rendering.py +0 -0
  230. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_labels/test_no_clipping.py +0 -0
  231. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_labels/test_ylabel_clearance.py +0 -0
  232. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_layouts/__init__.py +0 -0
  233. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_layouts/test_batch.py +0 -0
  234. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_layouts/test_coord_conversion.py +0 -0
  235. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_layouts/test_geom_channel.py +0 -0
  236. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_layouts/test_gridspec.py +0 -0
  237. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_layouts/test_inset.py +0 -0
  238. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_layouts/test_inset_callout.py +0 -0
  239. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_layouts/test_interaction.py +0 -0
  240. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_layouts/test_visual.py +0 -0
  241. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_markers/__init__.py +0 -0
  242. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_markers/test_marker_transforms.py +0 -0
  243. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_markers/test_markers.py +0 -0
  244. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_markers/test_per_marker_colors.py +0 -0
  245. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_markers/test_size_units.py +0 -0
  246. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_plot1d/__init__.py +0 -0
  247. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_plot1d/test_line_none_rendering.py +0 -0
  248. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_plot1d/test_plot1d.py +0 -0
  249. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_plot1d/test_plotbar.py +0 -0
  250. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_plot2d/__init__.py +0 -0
  251. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_plot2d/test_colorbar_gap_scalebar.py +0 -0
  252. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_plot2d/test_detail_tile.py +0 -0
  253. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_plot2d/test_display_window.py +0 -0
  254. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_plot2d/test_first_paint_race.py +0 -0
  255. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_plot2d/test_gpu_image.py +0 -0
  256. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_plot2d/test_gpu_parity_playwright.py +0 -0
  257. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_plot2d/test_imshow.py +0 -0
  258. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_plot2d/test_imshow_rgb.py +0 -0
  259. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_plot2d/test_layers.py +0 -0
  260. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_plot2d/test_layers_playwright.py +0 -0
  261. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_plot2d/test_pcolormesh.py +0 -0
  262. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_plot2d/test_plot2d_api.py +0 -0
  263. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_plot2d/test_rapid_frame_update.py +0 -0
  264. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_plot2d/test_tile_diagnostics.py +0 -0
  265. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_plot2d/test_tiled_imshow.py +0 -0
  266. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_plot2d/test_zoom_view_write.py +0 -0
  267. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_plot3d/__init__.py +0 -0
  268. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_plot3d/test_colors_highlight.py +0 -0
  269. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_plot3d/test_gpu_depth.py +0 -0
  270. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_plot3d/test_gpu_fallback.py +0 -0
  271. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_plot3d/test_gpu_hidden_reveal.py +0 -0
  272. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_plot3d/test_plot3d.py +0 -0
  273. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_plot3d/test_texture.py +0 -0
  274. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_plot3d/test_voxels_planes.py +0 -0
  275. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/tests/test_plotxy/test_plotxy.py +0 -0
  276. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/widgets/__init__.py +0 -0
  277. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/widgets/_base.py +0 -0
  278. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/widgets/_widgets1d.py +0 -0
  279. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/widgets/_widgets2d.py +0 -0
  280. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/anyplotlib/widgets/_widgets3d.py +0 -0
  281. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/docs/_sg_html_scraper.py +0 -0
  282. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/docs/_static/anyplotlib.svg +0 -0
  283. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/docs/_static/custom.css +0 -0
  284. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/docs/_static/pyodide_bridge.js +0 -0
  285. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/docs/_templates/autosummary/class.rst +0 -0
  286. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/docs/api/callbacks.rst +0 -0
  287. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/docs/api/figure.rst +0 -0
  288. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/docs/api/figure_plots.rst +0 -0
  289. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/docs/api/index.rst +0 -0
  290. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/docs/api/keys.rst +0 -0
  291. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/docs/api/markers.rst +0 -0
  292. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/docs/api/widgets.rst +0 -0
  293. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/docs/benchmarking.rst +0 -0
  294. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/docs/dev/index.rst +0 -0
  295. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/docs/getting_started.rst +0 -0
  296. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/make.bat +0 -0
  297. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/upcoming_changes/.gitkeep +0 -0
  298. {anyplotlib-0.8.0 → anyplotlib-0.9.0}/upcoming_changes/README.rst +0 -0
@@ -7,7 +7,7 @@
7
7
  - **`Figure`** (`anyplotlib/figure/_figure.py`) — the only `anywidget.AnyWidget` subclass. Owns all traitlets and is the Python↔JS bridge.
8
8
  - **Plot objects** (`plot1d/`, `plot2d/`, `plot3d/`) — `Plot1D`, `PlotBar`, `Plot2D`, `PlotMesh`, `Plot3D` are **plain Python classes**, not widgets. They hold state in `_state` dicts and push to the Figure. Shared behaviour lives in `_base_plot.py` (`_BasePlot`, `_PanelMixin`, `_MarkerMixin`).
9
9
  - **`Axes`** (`axes/_axes.py`) — grid-cell container; factory methods (`imshow`, `plot`, `bar`, `pcolormesh`, `plot_surface`, …) create plot objects and attach them.
10
- - **`figure_esm.js`** — pure-JS canvas renderer (~9,300 lines); all rendering logic lives here. **Read `anyplotlib/FIGURE_ESM.md` first** — it is the section map.
10
+ - **`figure_esm.js`** — pure-JS canvas renderer (~12,210 lines); all rendering logic lives here. **Read `anyplotlib/FIGURE_ESM.md` first** — it is the section map.
11
11
  - **`markers.py`** — static visual overlays (circles, arrows, lines, etc.) with a two-level dict registry: `plot.markers[type][name]`.
12
12
  - **`widgets/`** — interactive draggable overlays (`RectangleWidget`, `CrosshairWidget`, etc.) that receive JS position updates.
13
13
  - **`callbacks.py`** — event system: `Event` dataclass, `CallbackRegistry` (priority ordering, wildcard, pause/hold), `_EventMixin` (`add_event_handler`).
@@ -115,7 +115,7 @@ grep -nE '^\s*(function|const|let) [A-Za-z_]' anyplotlib/figure_esm.js
115
115
  ```
116
116
 
117
117
  and reconcile against the two numbered tables (the section map near the top and
118
- the 2-D function table). Both were last verified at 10,119 lines.
118
+ the 2-D function table). Both were last verified at 12,211 lines.
119
119
 
120
120
  Changelog entries: add a fragment file to `upcoming_changes/` (e.g.
121
121
  `123.new_feature.rst`) — towncrier assembles `CHANGELOG.rst` at release time.
@@ -129,7 +129,7 @@ Use `api_change` when existing behaviour changes, even if the change is a fix.
129
129
  | `anyplotlib/figure/_gridspec.py` | `GridSpec`, `SubplotSpec` |
130
130
  | `anyplotlib/figure/_subplots.py` | `subplots()` factory |
131
131
  | `anyplotlib/axes/_axes.py` | `Axes` — plot factory methods |
132
- | `anyplotlib/figure_esm.js` | All JS canvas rendering (~9,300 lines) |
132
+ | `anyplotlib/figure_esm.js` | All JS canvas rendering (~12,210 lines) |
133
133
  | `anyplotlib/FIGURE_ESM.md` | Section map for `figure_esm.js` — read this before editing the JS |
134
134
  | `anyplotlib/markers.py` | Static marker collections; `to_wire()` translation |
135
135
  | `anyplotlib/widgets/` | Interactive overlay widgets |
@@ -10,6 +10,122 @@ Fragment files in ``upcoming_changes/`` are assembled into this file by
10
10
 
11
11
  .. towncrier release notes start
12
12
 
13
+ 0.9.0 (2026-09-11)
14
+ ==================
15
+
16
+ New Features
17
+ ------------
18
+
19
+ - A self-contained HTML page can now navigate its own data.
20
+ ``anyplotlib.embed.navigated_html`` writes a figure, the dataset it navigates
21
+ and a list of bindings into one file: drag the navigator's crosshair and the
22
+ signal panel shows that position's frame, its overlays follow, and a detector
23
+ drawn on the signal panel re-maps the navigator. Data travels as *blocks*:
24
+ dense arrays, or ``Ragged`` row-pointer blocks for a variable number of rows
25
+ per position, packed by ``pack_blocks`` into one byte string the page decodes
26
+ once.
27
+
28
+ The JS mount handle gained the pieces that make that fast: ``setImage`` pushes
29
+ raw pixel bytes straight to the renderer's draw path (a fraction of a
30
+ millisecond at 2048², against 129-136 ms through the panel state),
31
+ ``patchPanel`` merges a partial state, and ``panelIds`` lists the panels. The
32
+ runtime and its readers (``mountNavigated``, ``dense``, ``ragged``,
33
+ ``maskFromWidget``, ``rasterDisks``, ``robustLevels``, ``toU8``) are exported
34
+ from ``figure_esm.js`` for hosts that already own their data. (`#69 <https://github.com/CSSFrancis/anyplotlib/pull/69>`_)
35
+ - Figures can now be **saved and copied as PNG images**. Right-click any plot for a
36
+ menu offering *Copy image*, *Save PNG…*, *Save full view…* and *Save at native
37
+ resolution…* for the panel you clicked, the same for the whole figure, and a
38
+ sticky **Theme** choice (*Current* / *Light* / *Dark*) so a dark-themed notebook
39
+ can still produce a light figure for a paper. ``Ctrl+C`` (``Cmd+C`` on macOS)
40
+ copies the plot under the cursor to the clipboard, with a brief
41
+ *"Image copied to clipboard"* confirmation; with no plot hovered it copies the
42
+ whole figure. Inside JupyterLab, PyCharm and VS Code the badge is the reliable
43
+ route: those hosts install their own ``contextmenu`` and keyboard handlers and
44
+ may swallow a right-click or ``Cmd+C`` before the figure ever sees it. *Save PNG…* downloads without any permission prompt; a separate *Save as…*
45
+ entry opens a real system file dialog where the browser supports one
46
+ (Chromium), at the cost of Chrome's file-editing permission prompt. Hosts that
47
+ block script-started downloads get an in-figure preview instead.
48
+ The three sources are *current view* (zoom, pan and contrast
49
+ exactly as displayed), *full view* (the whole data extent at the panel's
50
+ on-screen resolution) and *native resolution* (one output pixel per data pixel,
51
+ with the axes, colorbar, title, markers and widgets all redrawn at that size).
52
+
53
+ The same thing is available from Python as :meth:`~anyplotlib.Figure.savefig`::
54
+
55
+ fig.savefig("figure.png") # as displayed
56
+ fig.savefig("paper.png", theme="light", scale=2) # light, 2x
57
+ fig.savefig("data.png", source="native", panel=plot) # 1:1 with the data
58
+
59
+ ``savefig`` renders through the real JavaScript renderer in a headless browser,
60
+ so the output is exactly what the figure looks like on screen — it needs
61
+ Playwright (``pip install "anyplotlib[docs]"`` then
62
+ ``playwright install chromium``). ``source="native"`` works even for a **tiled**
63
+ plot, whose full-resolution array normally never leaves Python: the backend is
64
+ re-sampled at full resolution for the export only, leaving the live figure
65
+ untouched. In the browser that case is offered but disabled, with a tooltip
66
+ pointing at ``savefig``, because the page only ever holds a downsampled
67
+ overview.
68
+
69
+ Downstream applications can add their own entries to the menu through the
70
+ embedding handle, so a host can save formats anyplotlib knows nothing about::
71
+
72
+ handle.registerExportAction({
73
+ id: 'save-tiff', label: 'Save as TIFF…', scope: 'panel',
74
+ handler: (ctx) => host.writeTiff(ctx.panelId, ctx.exportCanvas().canvas),
75
+ })
76
+
77
+ The handler receives the clicked panel, its state, the chosen theme, and bound
78
+ ``exportPNG`` / ``exportCanvas`` / ``downloadPNG`` / ``copyPNG`` / ``toast``
79
+ helpers. See :doc:`exporting` for the full reference.
80
+ - The 2-D hover readout now also names the **value** of the pixel under the
81
+ cursor — ``v:<value>`` for a colourmapped image, ``rgb:r,g,b`` for a true-colour
82
+ one — alongside the existing physical and pixel coordinates. It is exact:
83
+ integer data whose range fits the 256 transferred codes is inverted locally,
84
+ and for anything wider the renderer asks Python for the true value once the
85
+ cursor dwells on a pixel (``imshow(..., probe_exact=True)`` by default, tunable
86
+ via :meth:`~anyplotlib.Plot2D.set_value_probe`), falling back to the quantised
87
+ estimate when no kernel can answer. Zoomed into a detail tile the value comes
88
+ from the tile's native pixels rather than the coarser overview.
89
+ The **v** key toggles the on-image pill, and
90
+ :meth:`~anyplotlib.Plot2D.set_readout_visible` turns it off from Python while
91
+ keeping the readout live: embedding hosts receive every update through
92
+ ``mount()``'s ``opts.onReadout`` callback and an ``apl:readout`` DOM event — so
93
+ an Electron app can render position and value in its own status bar instead,
94
+ where it covers no data. 2-D pointer events also carry ``img_x``/``img_y`` now,
95
+ the cursor's position in image pixels.
96
+
97
+
98
+ Bug Fixes
99
+ ---------
100
+
101
+ - Fixed a tiled :meth:`~anyplotlib.Axes.imshow` of a **signed** integer frame
102
+ displaying wrapped values: a ``uint32`` accumulator in the overview box-mean read
103
+ an ``int16`` ``-100`` as ``+1073741696``, raised
104
+ ``_UFuncOutputCastingError`` on a non-divisible grid, and overflowed on any dtype
105
+ wider than 16 bits; the accumulator is now sized to the data, which also makes the
106
+ overview up to 4x faster on large float frames. (`#65 <https://github.com/CSSFrancis/anyplotlib/pull/65>`_)
107
+ - :meth:`~anyplotlib.Figure.save_html`, :func:`~anyplotlib.embed.to_html` and
108
+ :func:`~anyplotlib.embed.figure_state` now capture the view the reader is
109
+ actually looking at. Zoom, pan, orbit and the colorbar / scale-mode shortcuts
110
+ are applied in the browser and written back to the panel traits, but nothing on
111
+ the Python side read them back, so every snapshot silently reset the figure to
112
+ the view it was created with. Those keys are now reconciled into the plot state
113
+ before a snapshot is taken.
114
+ - Fixed PNG export producing a mostly-blank image when the figure is wider than
115
+ the notebook cell. In that case the renderer shrinks the figure with a CSS
116
+ ``transform: scale()``, which makes element rectangles report *visual* pixels
117
+ while the export sized its canvas in *native* pixels — so the panels were
118
+ composited into the top-left corner and the remainder was filled with the
119
+ background colour. Export coordinates are now un-scaled by the live transform.
120
+ - Modified key presses no longer trigger a plot's single-letter shortcuts. The
121
+ panel key handlers matched on the bare letter without checking modifiers, so
122
+ ``Ctrl+C`` toggled the colorbar instead of copying, and ``Cmd+S`` — JupyterLab's
123
+ *save notebook* — silently flipped a 2-D plot's colour scale to symlog. Keys
124
+ pressed with ``Ctrl``, ``Cmd`` or ``Alt`` are now left to the host. They are
125
+ still reported to Python ``key_down`` callbacks exactly as before, so nothing
126
+ that observes the full keystroke changes.
127
+
128
+
13
129
  0.8.0 (2026-08-25)
14
130
  ==================
15
131
 
@@ -0,0 +1,77 @@
1
+ """
2
+ Aspect Ratio Control
3
+ ====================
4
+
5
+ :meth:`~anyplotlib.Plot2D.set_aspect` constrains the displayed image canvas so
6
+ that one unit on the x-axis occupies the same number of pixels as one unit on
7
+ the y-axis.
8
+
9
+ Three modes are shown:
10
+
11
+ 1. **Default** — the image fills the panel exactly (no constraint).
12
+ 2. ``set_aspect("equal")`` — forces a 1 : 1 pixel-per-unit ratio. A square
13
+ array is displayed as a square image regardless of panel dimensions.
14
+ 3. ``set_aspect(2.0)`` — makes the canvas twice as wide as it is tall.
15
+
16
+ The scale bar, axis ticks, and colorbar all update automatically when the
17
+ canvas is resized by ``set_aspect``.
18
+ """
19
+ import numpy as np
20
+ import anyplotlib as apl
21
+
22
+ rng = np.random.default_rng(0)
23
+
24
+ # ── Synthetic calibrated image ────────────────────────────────────────────────
25
+ N = 64
26
+ x = np.linspace(0, 10, N) # nm
27
+ y = np.linspace(0, 10, N)
28
+ XX, YY = np.meshgrid(x, y)
29
+ data = (np.sin(XX) * np.cos(YY) + 0.2 * rng.standard_normal((N, N))).astype(np.float32)
30
+
31
+ # ── 1. Default (no aspect constraint) ────────────────────────────────────────
32
+ # %%
33
+ # Default — no aspect constraint
34
+ # --------------------------------
35
+ # The image stretches to fill the full panel area.
36
+
37
+ fig1, ax1 = apl.subplots(1, 1, figsize=(420, 340))
38
+ plot1 = ax1.imshow(data, axes=[x, y], units="nm", cmap="viridis")
39
+ plot1.set_title("Default (no constraint)")
40
+ plot1.set_xlabel("x (nm)")
41
+ plot1.set_ylabel("y (nm)")
42
+
43
+ fig1 # Interactive
44
+
45
+ # ── 2. Equal aspect ratio ─────────────────────────────────────────────────────
46
+ # %%
47
+ # Equal aspect ratio
48
+ # ------------------
49
+ # ``set_aspect("equal")`` (or equivalently ``set_aspect(1.0)``) ensures that
50
+ # one nm on the x-axis occupies the same number of canvas pixels as one nm on
51
+ # the y-axis. The canvas height adjusts to be equal to the canvas width.
52
+
53
+ fig2, ax2 = apl.subplots(1, 1, figsize=(420, 340))
54
+ plot2 = ax2.imshow(data, axes=[x, y], units="nm", cmap="viridis")
55
+ plot2.set_aspect("equal")
56
+ plot2.set_title("set_aspect('equal')")
57
+ plot2.set_xlabel("x (nm)")
58
+ plot2.set_ylabel("y (nm)")
59
+
60
+ fig2 # Interactive
61
+
62
+ # ── 3. Explicit ratio ─────────────────────────────────────────────────────────
63
+ # %%
64
+ # Explicit ratio (2 : 1)
65
+ # -----------------------
66
+ # ``set_aspect(2.0)`` makes the canvas twice as wide as it is tall. Useful
67
+ # when the physical x and y scales differ (e.g. a time-series scan where one
68
+ # axis is faster than the other).
69
+
70
+ fig3, ax3 = apl.subplots(1, 1, figsize=(420, 340))
71
+ plot3 = ax3.imshow(data, axes=[x, y], units="nm", cmap="inferno")
72
+ plot3.set_aspect(2.0)
73
+ plot3.set_title("set_aspect(2.0)")
74
+ plot3.set_xlabel("x (nm)")
75
+ plot3.set_ylabel("y (nm)")
76
+
77
+ fig3 # Interactive
@@ -0,0 +1,90 @@
1
+ """
2
+ Subplot Spacing with subplots_adjust
3
+ =====================================
4
+
5
+ :meth:`~anyplotlib.Figure.subplots_adjust` controls the gap between panels in
6
+ a multi-panel figure.
7
+
8
+ * **hspace** — vertical gap as a fraction of the mean row height.
9
+ ``hspace=0.15`` adds 15 % of the average row height as space between rows.
10
+ * **wspace** — horizontal gap as a fraction of the mean column width.
11
+ ``wspace=0.10`` adds 10 % of the average column width as space between
12
+ columns.
13
+
14
+ Both values default to ``0.0`` (panels are flush with no gap).
15
+
16
+ The examples below compare default flush spacing against adjusted spacing on
17
+ the same 2 × 2 grid.
18
+ """
19
+ import numpy as np
20
+ import anyplotlib as apl
21
+
22
+ rng = np.random.default_rng(42)
23
+ t = np.linspace(0, 2 * np.pi, 512)
24
+
25
+ COLORS = ["#4fc3f7", "#ff7043", "#aed581", "#ffd54f"]
26
+ LABELS = ["α", "β", "γ", "δ"]
27
+ SIGNALS = [
28
+ np.sin(t * (i + 1)) + rng.normal(scale=0.08, size=len(t))
29
+ for i in range(4)
30
+ ]
31
+
32
+
33
+ def _fill_grid(fig):
34
+ """Add four 1-D spectra to a 2×2 Figure."""
35
+ import anyplotlib as _apl
36
+ gs = _apl.GridSpec(2, 2)
37
+ positions = [(0, 0), (0, 1), (1, 0), (1, 1)]
38
+ for idx, (r, c) in enumerate(positions):
39
+ ax = fig.add_subplot(gs[r, c])
40
+ ax.plot(SIGNALS[idx], color=COLORS[idx], label=LABELS[idx])
41
+
42
+
43
+ # ── 1. Default spacing (flush) ────────────────────────────────────────────────
44
+ # %%
45
+ # Default spacing — panels flush
46
+ # --------------------------------
47
+ # Without calling ``subplots_adjust`` the panels abut each other with no gap.
48
+
49
+ fig1 = apl.Figure(2, 2, figsize=(680, 480))
50
+ _fill_grid(fig1)
51
+
52
+ fig1 # Interactive
53
+
54
+ # ── 2. Vertical gap only (hspace) ────────────────────────────────────────────
55
+ # %%
56
+ # Vertical gap only — hspace=0.15
57
+ # ---------------------------------
58
+ # ``subplots_adjust(hspace=0.15)`` inserts a vertical gap equal to 15 % of
59
+ # the mean row height between the two rows.
60
+
61
+ fig2 = apl.Figure(2, 2, figsize=(680, 480))
62
+ _fill_grid(fig2)
63
+ fig2.subplots_adjust(hspace=0.15)
64
+
65
+ fig2 # Interactive
66
+
67
+ # ── 3. Horizontal gap only (wspace) ──────────────────────────────────────────
68
+ # %%
69
+ # Horizontal gap only — wspace=0.10
70
+ # -----------------------------------
71
+ # ``subplots_adjust(wspace=0.10)`` inserts a horizontal gap equal to 10 % of
72
+ # the mean column width between the two columns.
73
+
74
+ fig3 = apl.Figure(2, 2, figsize=(680, 480))
75
+ _fill_grid(fig3)
76
+ fig3.subplots_adjust(wspace=0.10)
77
+
78
+ fig3 # Interactive
79
+
80
+ # ── 4. Both gaps ─────────────────────────────────────────────────────────────
81
+ # %%
82
+ # Both hspace and wspace
83
+ # -----------------------
84
+ # Combine both arguments to add space in both directions.
85
+
86
+ fig4 = apl.Figure(2, 2, figsize=(680, 480))
87
+ _fill_grid(fig4)
88
+ fig4.subplots_adjust(hspace=0.15, wspace=0.10)
89
+
90
+ fig4 # Interactive
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: anyplotlib
3
- Version: 0.8.0
3
+ Version: 0.9.0
4
4
  Summary: A plotting library using python, javascript and anywidget for performant in browser plotting.
5
5
  Project-URL: Homepage, https://cssfrancis.github.io/anyplotlib/
6
6
  Project-URL: Repository, https://github.com/CSSFrancis/anyplotlib