glplot 0.1.6__tar.gz → 0.1.7__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.
- {glplot-0.1.6 → glplot-0.1.7}/.gitignore +4 -0
- glplot-0.1.7/PKG-INFO +576 -0
- glplot-0.1.7/README.md +534 -0
- {glplot-0.1.6 → glplot-0.1.7}/glplot/__init__.py +1 -1
- {glplot-0.1.6 → glplot-0.1.7}/glplot/animation.py +7 -2
- {glplot-0.1.6 → glplot-0.1.7}/glplot/controllers.py +2 -3
- {glplot-0.1.6 → glplot-0.1.7}/glplot/core/camera3d.py +4 -2
- {glplot-0.1.6 → glplot-0.1.7}/glplot/core/context.py +2 -2
- {glplot-0.1.6 → glplot-0.1.7}/glplot/core/layers.py +2 -3
- {glplot-0.1.6 → glplot-0.1.7}/glplot/core/timeline.py +1 -1
- {glplot-0.1.6 → glplot-0.1.7}/glplot/engine.py +43 -40
- {glplot-0.1.6 → glplot-0.1.7}/glplot/gui/dynamics.py +1 -1
- {glplot-0.1.6 → glplot-0.1.7}/glplot/gui/generators3d.py +2 -2
- {glplot-0.1.6 → glplot-0.1.7}/glplot/gui/panels/annotate.py +2 -1
- {glplot-0.1.6 → glplot-0.1.7}/glplot/gui/panels/objects3d.py +1 -1
- {glplot-0.1.6 → glplot-0.1.7}/glplot/gui/styles.py +140 -0
- {glplot-0.1.6 → glplot-0.1.7}/glplot/gui/workspace.py +5 -2
- {glplot-0.1.6 → glplot-0.1.7}/glplot/managers/axis.py +3 -1
- {glplot-0.1.6 → glplot-0.1.7}/glplot/managers/effects.py +0 -1
- {glplot-0.1.6 → glplot-0.1.7}/glplot/managers/hud.py +6 -7
- {glplot-0.1.6 → glplot-0.1.7}/glplot/managers/hud_state.py +1 -3
- {glplot-0.1.6 → glplot-0.1.7}/glplot/managers/picking.py +0 -4
- {glplot-0.1.6 → glplot-0.1.7}/glplot/managers/renderer_manager.py +25 -16
- {glplot-0.1.6 → glplot-0.1.7}/glplot/policy.py +3 -5
- {glplot-0.1.6 → glplot-0.1.7}/glplot/pyplot.py +47 -32
- {glplot-0.1.6 → glplot-0.1.7}/glplot/renderers/axes3d.py +2 -1
- {glplot-0.1.6 → glplot-0.1.7}/glplot/renderers/density.py +1 -5
- {glplot-0.1.6 → glplot-0.1.7}/glplot/renderers/line_family.py +1 -1
- {glplot-0.1.6 → glplot-0.1.7}/glplot/renderers/patch.py +1 -1
- {glplot-0.1.6 → glplot-0.1.7}/glplot/renderers/scatter.py +1 -1
- {glplot-0.1.6 → glplot-0.1.7}/glplot/renderers/text.py +3 -3
- {glplot-0.1.6 → glplot-0.1.7}/glplot/utils/anim_export.py +6 -2
- {glplot-0.1.6 → glplot-0.1.7}/glplot/utils/gl_utils.py +3 -3
- {glplot-0.1.6 → glplot-0.1.7}/glplot/utils/preview.py +264 -24
- {glplot-0.1.6 → glplot-0.1.7}/glplot/utils/shaders.py +6 -5
- {glplot-0.1.6 → glplot-0.1.7}/pyproject.toml +12 -1
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_api_consistency.py +2 -2
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_axis_margins.py +0 -3
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_camera_anisotropy.py +1 -1
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_camera_projections.py +0 -5
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_export.py +76 -0
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_function_layer.py +4 -1
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_gallery_integration.py +0 -1
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_geometry3d.py +2 -2
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_gui_3d_panels.py +2 -2
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_gui_layer_kinds.py +5 -2
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_gui_layer_params.py +1 -1
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_gui_style_layer_editor.py +6 -4
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_gui_styles_extra.py +2 -2
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_layers.py +0 -1
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_mpl_bridge.py +3 -3
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_mpl_compat.py +1 -1
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_options.py +0 -2
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_outline_2d.py +2 -2
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_panels.py +43 -1
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_polyline_lod.py +2 -7
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_pyplot.py +23 -0
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_pyplot_integration.py +2 -2
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_regression.py +1 -1
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_robustness.py +3 -3
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_scatter_renderer.py +2 -2
- glplot-0.1.6/.claude/agents/glplot-api-analyzer.md +0 -67
- glplot-0.1.6/.claude/agents/glplot-bug-reporter.md +0 -83
- glplot-0.1.6/.claude/agents/glplot-documentation-auditor.md +0 -80
- glplot-0.1.6/.claude/agents/glplot-performance-profiler.md +0 -76
- glplot-0.1.6/.claude/agents/glplot-release-manager.md +0 -80
- glplot-0.1.6/.claude/agents/glplot-test-runner.md +0 -57
- glplot-0.1.6/.github/workflows/build.yml +0 -37
- glplot-0.1.6/.github/workflows/lint.yml +0 -33
- glplot-0.1.6/.github/workflows/tests.yml +0 -42
- glplot-0.1.6/.gitlab-ci.yml +0 -107
- glplot-0.1.6/.readthedocs.yml +0 -43
- glplot-0.1.6/CODE_OF_CONDUCT.md +0 -47
- glplot-0.1.6/CONTRIBUTING.md +0 -98
- glplot-0.1.6/DOCUMENTATION_SETUP.md +0 -210
- glplot-0.1.6/GLPlot_Architecture_and_Mathematical_Formulation.md +0 -260
- glplot-0.1.6/JOSS_READINESS.md +0 -158
- glplot-0.1.6/PKG-INFO +0 -433
- glplot-0.1.6/PUBLICATION_CHECKLIST.md +0 -104
- glplot-0.1.6/PUBLICATION_WORKFLOW.md +0 -384
- glplot-0.1.6/README.md +0 -391
- glplot-0.1.6/READY_FOR_PUBLICATION.md +0 -253
- glplot-0.1.6/build_and_upload.sh +0 -77
- glplot-0.1.6/docs/Makefile +0 -148
- glplot-0.1.6/docs/README.md +0 -244
- glplot-0.1.6/docs/requirements.txt +0 -7
- glplot-0.1.6/docs/source/_static/custom.css +0 -119
- glplot-0.1.6/docs/source/api/core.rst +0 -26
- glplot-0.1.6/docs/source/api/layers.rst +0 -77
- glplot-0.1.6/docs/source/api/managers.rst +0 -66
- glplot-0.1.6/docs/source/api/plotting.rst +0 -63
- glplot-0.1.6/docs/source/api/utilities.rst +0 -65
- glplot-0.1.6/docs/source/conf.py +0 -88
- glplot-0.1.6/docs/source/dev/architecture.rst +0 -639
- glplot-0.1.6/docs/source/dev/contributing.rst +0 -636
- glplot-0.1.6/docs/source/dev/index.rst +0 -236
- glplot-0.1.6/docs/source/dev/testing.rst +0 -811
- glplot-0.1.6/docs/source/gallery/gallery.rst +0 -102
- glplot-0.1.6/docs/source/guide/2d-plotting.rst +0 -832
- glplot-0.1.6/docs/source/guide/3d-visualization.rst +0 -925
- glplot-0.1.6/docs/source/guide/advanced-features.rst +0 -1028
- glplot-0.1.6/docs/source/guide/basic-plotting.rst +0 -258
- glplot-0.1.6/docs/source/guide/installation.rst +0 -115
- glplot-0.1.6/docs/source/guide/performance-tips.rst +0 -184
- glplot-0.1.6/docs/source/guide/quickstart.rst +0 -200
- glplot-0.1.6/docs/source/index.rst +0 -52
- glplot-0.1.6/examples/benchmark/01_line_density.py +0 -263
- glplot-0.1.6/examples/benchmark/02_gpu_comparison.py +0 -635
- glplot-0.1.6/examples/benchmark/03_density_quality_comparison.py +0 -221
- glplot-0.1.6/examples/benchmark/04_hvplot_datashader_interactive.py +0 -83
- glplot-0.1.6/examples/benchmark/05_pipeline_diagram.py +0 -503
- glplot-0.1.6/examples/benchmark/results/datashader_density_1000.png +0 -0
- glplot-0.1.6/examples/benchmark/results/datashader_density_10000.png +0 -0
- glplot-0.1.6/examples/benchmark/results/datashader_density_100000.png +0 -0
- glplot-0.1.6/examples/benchmark/results/datashader_density_1000000.png +0 -0
- glplot-0.1.6/examples/benchmark/results/datashader_density_10000000.png +0 -0
- glplot-0.1.6/examples/benchmark/results/density_quality_comparison.png +0 -0
- glplot-0.1.6/examples/benchmark/results/density_quality_fastplotlib.png +0 -0
- glplot-0.1.6/examples/benchmark/results/density_quality_glplot.png +0 -0
- glplot-0.1.6/examples/benchmark/results/density_quality_vispy.png +0 -0
- glplot-0.1.6/examples/benchmark/results/fastplotlib_gpu_lines_10.png +0 -0
- glplot-0.1.6/examples/benchmark/results/fastplotlib_gpu_lines_100.png +0 -0
- glplot-0.1.6/examples/benchmark/results/fastplotlib_gpu_lines_1000.png +0 -0
- glplot-0.1.6/examples/benchmark/results/fastplotlib_gpu_lines_10000.png +0 -0
- glplot-0.1.6/examples/benchmark/results/fastplotlib_gpu_lines_100000.png +0 -0
- glplot-0.1.6/examples/benchmark/results/fastplotlib_gpu_lines_1000000.png +0 -0
- glplot-0.1.6/examples/benchmark/results/fastplotlib_gpu_lines_10000000.png +0 -0
- glplot-0.1.6/examples/benchmark/results/glplot_density_10.png +0 -0
- glplot-0.1.6/examples/benchmark/results/glplot_density_100.png +0 -0
- glplot-0.1.6/examples/benchmark/results/glplot_density_1000.png +0 -0
- glplot-0.1.6/examples/benchmark/results/glplot_density_10000.png +0 -0
- glplot-0.1.6/examples/benchmark/results/glplot_density_100000.png +0 -0
- glplot-0.1.6/examples/benchmark/results/glplot_density_1000000.png +0 -0
- glplot-0.1.6/examples/benchmark/results/glplot_gpu_density_10.png +0 -0
- glplot-0.1.6/examples/benchmark/results/glplot_gpu_density_100.png +0 -0
- glplot-0.1.6/examples/benchmark/results/glplot_gpu_density_1000.png +0 -0
- glplot-0.1.6/examples/benchmark/results/glplot_gpu_density_10000.png +0 -0
- glplot-0.1.6/examples/benchmark/results/glplot_gpu_density_100000.png +0 -0
- glplot-0.1.6/examples/benchmark/results/glplot_gpu_density_1000000.png +0 -0
- glplot-0.1.6/examples/benchmark/results/glplot_gpu_density_10000000.png +0 -0
- glplot-0.1.6/examples/benchmark/results/glplot_gpu_density_100000000.png +0 -0
- glplot-0.1.6/examples/benchmark/results/glplot_gpu_exact_10.png +0 -0
- glplot-0.1.6/examples/benchmark/results/glplot_gpu_exact_100.png +0 -0
- glplot-0.1.6/examples/benchmark/results/glplot_gpu_exact_1000.png +0 -0
- glplot-0.1.6/examples/benchmark/results/glplot_gpu_exact_10000.png +0 -0
- glplot-0.1.6/examples/benchmark/results/glplot_gpu_exact_100000.png +0 -0
- glplot-0.1.6/examples/benchmark/results/glplot_gpu_exact_1000000.png +0 -0
- glplot-0.1.6/examples/benchmark/results/glplot_gpu_exact_10000000.png +0 -0
- glplot-0.1.6/examples/benchmark/results/glplot_gpu_exact_100000000.png +0 -0
- glplot-0.1.6/examples/benchmark/results/glplot_pipeline_diagram.png +0 -0
- glplot-0.1.6/examples/benchmark/results/gpu_comparison_benchmark_results.png +0 -0
- glplot-0.1.6/examples/benchmark/results/hvplot_density_1000.png +0 -0
- glplot-0.1.6/examples/benchmark/results/hvplot_density_10000.png +0 -0
- glplot-0.1.6/examples/benchmark/results/hvplot_density_100000.png +0 -0
- glplot-0.1.6/examples/benchmark/results/hvplot_density_1000000.png +0 -0
- glplot-0.1.6/examples/benchmark/results/hvplot_density_10000000.png +0 -0
- glplot-0.1.6/examples/benchmark/results/hvplot_lines_1000.png +0 -0
- glplot-0.1.6/examples/benchmark/results/hvplot_lines_10000.png +0 -0
- glplot-0.1.6/examples/benchmark/results/hvplot_lines_100000.png +0 -0
- glplot-0.1.6/examples/benchmark/results/line_density_benchmark_results.png +0 -0
- glplot-0.1.6/examples/benchmark/results/matplotlib_density_10.png +0 -0
- glplot-0.1.6/examples/benchmark/results/matplotlib_density_100.png +0 -0
- glplot-0.1.6/examples/benchmark/results/matplotlib_density_1000.png +0 -0
- glplot-0.1.6/examples/benchmark/results/matplotlib_density_10000.png +0 -0
- glplot-0.1.6/examples/benchmark/results/matplotlib_density_100000.png +0 -0
- glplot-0.1.6/examples/benchmark/results/matplotlib_density_1000000.png +0 -0
- glplot-0.1.6/examples/benchmark/results/matplotlib_lines_10.png +0 -0
- glplot-0.1.6/examples/benchmark/results/matplotlib_lines_100.png +0 -0
- glplot-0.1.6/examples/benchmark/results/matplotlib_lines_1000.png +0 -0
- glplot-0.1.6/examples/benchmark/results/matplotlib_lines_10000.png +0 -0
- glplot-0.1.6/examples/benchmark/results/matplotlib_lines_100000.png +0 -0
- glplot-0.1.6/examples/benchmark/results/vispy_gpu_lines_10.png +0 -0
- glplot-0.1.6/examples/benchmark/results/vispy_gpu_lines_100.png +0 -0
- glplot-0.1.6/examples/benchmark/results/vispy_gpu_lines_1000.png +0 -0
- glplot-0.1.6/examples/benchmark/results/vispy_gpu_lines_10000.png +0 -0
- glplot-0.1.6/examples/benchmark/results/vispy_gpu_lines_100000.png +0 -0
- glplot-0.1.6/examples/benchmark/results/vispy_gpu_lines_1000000.png +0 -0
- glplot-0.1.6/examples/benchmark/results/vispy_gpu_lines_10000000.png +0 -0
- glplot-0.1.6/examples/benchmark/vispy_interactive.py +0 -58
- glplot-0.1.6/examples/dataflow.png +0 -0
- glplot-0.1.6/examples/ex_aspect_ratio_fix.py +0 -61
- glplot-0.1.6/examples/ex_density.py +0 -48
- glplot-0.1.6/examples/ex_density_gain.py +0 -21
- glplot-0.1.6/examples/ex_expert_performance.py +0 -40
- glplot-0.1.6/examples/ex_full_showcase.py +0 -92
- glplot-0.1.6/examples/ex_function_plot.py +0 -151
- glplot-0.1.6/examples/ex_mandelbrot.py +0 -160
- glplot-0.1.6/examples/ex_mpl_bridge.py +0 -71
- glplot-0.1.6/examples/ex_read_density.py +0 -36
- glplot-0.1.6/examples/ex_scatter.py +0 -47
- glplot-0.1.6/examples/ex_simple.py +0 -22
- glplot-0.1.6/examples/ex_v2_layers.py +0 -60
- glplot-0.1.6/examples/ex_viewports.py +0 -50
- glplot-0.1.6/examples/free_energy_demo/compose.py +0 -101
- glplot-0.1.6/examples/free_energy_demo/data.py +0 -273
- glplot-0.1.6/examples/free_energy_demo/glplot_version.py +0 -608
- glplot-0.1.6/examples/free_energy_demo/mpl_version.py +0 -398
- glplot-0.1.6/examples/free_energy_demo/results/glplot_free_energy.png +0 -0
- glplot-0.1.6/examples/free_energy_demo/results/glplot_panels/a_inset.png +0 -0
- glplot-0.1.6/examples/free_energy_demo/results/glplot_panels/a_main.png +0 -0
- glplot-0.1.6/examples/free_energy_demo/results/glplot_panels/b_inset.png +0 -0
- glplot-0.1.6/examples/free_energy_demo/results/glplot_panels/b_main.png +0 -0
- glplot-0.1.6/examples/free_energy_demo/results/glplot_panels/c_inset.png +0 -0
- glplot-0.1.6/examples/free_energy_demo/results/glplot_panels/c_main.png +0 -0
- glplot-0.1.6/examples/free_energy_demo/results/glplot_panels/d_main.png +0 -0
- glplot-0.1.6/examples/free_energy_demo/results/glplot_panels/e_main.png +0 -0
- glplot-0.1.6/examples/free_energy_demo/results/glplot_panels/f_main.png +0 -0
- glplot-0.1.6/examples/free_energy_demo/results/matplotlib_free_energy.png +0 -0
- glplot-0.1.6/examples/free_energy_demo/results/mpl_panels/a_inset.png +0 -0
- glplot-0.1.6/examples/free_energy_demo/results/mpl_panels/a_main.png +0 -0
- glplot-0.1.6/examples/free_energy_demo/results/mpl_panels/b_inset.png +0 -0
- glplot-0.1.6/examples/free_energy_demo/results/mpl_panels/b_main.png +0 -0
- glplot-0.1.6/examples/free_energy_demo/results/mpl_panels/c_inset.png +0 -0
- glplot-0.1.6/examples/free_energy_demo/results/mpl_panels/c_main.png +0 -0
- glplot-0.1.6/examples/free_energy_demo/results/mpl_panels/d_main.png +0 -0
- glplot-0.1.6/examples/free_energy_demo/results/mpl_panels/e_main.png +0 -0
- glplot-0.1.6/examples/free_energy_demo/results/mpl_panels/f_main.png +0 -0
- glplot-0.1.6/examples/gallery/.gitignore +0 -1
- glplot-0.1.6/examples/gallery/01_line_plot.py +0 -25
- glplot-0.1.6/examples/gallery/02_scatter_fill.py +0 -27
- glplot-0.1.6/examples/gallery/03_bar_hist.py +0 -55
- glplot-0.1.6/examples/gallery/04_line_family_density.py +0 -32
- glplot-0.1.6/examples/gallery/05_guides_and_colormap.py +0 -34
- glplot-0.1.6/examples/gallery/06_signal_tools.py +0 -46
- glplot-0.1.6/examples/gallery/07_projected_3d_cloud.py +0 -33
- glplot-0.1.6/examples/gallery/08_vector_field_quiver.py +0 -39
- glplot-0.1.6/examples/gallery/09_large_matrix_heatmap.py +0 -21
- glplot-0.1.6/examples/gallery/10_massive_hist2d_density.py +0 -21
- glplot-0.1.6/examples/gallery/11_contour_pcolormesh_field.py +0 -32
- glplot-0.1.6/examples/gallery/12_surface_wireframe_bar3d.py +0 -60
- glplot-0.1.6/examples/gallery/13_volumetric_nebula.py +0 -48
- glplot-0.1.6/examples/gallery/14_bar3d_hex_box_city.py +0 -72
- glplot-0.1.6/examples/gallery/15_vector_field_3d.py +0 -63
- glplot-0.1.6/examples/gallery/16_ssao_comparison.py +0 -46
- glplot-0.1.6/examples/gallery/17_square_bars3d.py +0 -41
- glplot-0.1.6/examples/gallery/18_hex_bars3d.py +0 -40
- glplot-0.1.6/examples/gallery/19_turbulent_vector_field_3d.py +0 -106
- glplot-0.1.6/examples/gallery/20_categorical_bar_and_spines.py +0 -21
- glplot-0.1.6/examples/gallery/21_date_axis_and_text_bbox.py +0 -37
- glplot-0.1.6/examples/gallery/22_log_scale_plots.py +0 -21
- glplot-0.1.6/examples/gallery/23_symlog_scale.py +0 -23
- glplot-0.1.6/examples/gallery/24_log_scale_bar_chart.py +0 -18
- glplot-0.1.6/examples/gallery/25_log_scale_contourf.py +0 -21
- glplot-0.1.6/examples/gallery/26_logit_scale.py +0 -21
- glplot-0.1.6/examples/gallery/27_inset_axes_image.py +0 -51
- glplot-0.1.6/examples/gallery/README.md +0 -37
- glplot-0.1.6/examples/gallery/_preview.py +0 -1
- glplot-0.1.6/examples/gallery/results/.cache/matplotlib/fontlist-v330.json +0 -4884
- glplot-0.1.6/examples/gallery/results/.gitignore +0 -1
- glplot-0.1.6/examples/gallery/results/01_line_plot.png +0 -0
- glplot-0.1.6/examples/gallery/results/02_scatter_fill.png +0 -0
- glplot-0.1.6/examples/gallery/results/03_bar_hist.png +0 -0
- glplot-0.1.6/examples/gallery/results/04_line_family_density.png +0 -0
- glplot-0.1.6/examples/gallery/results/05_guides_and_colormap.png +0 -0
- glplot-0.1.6/examples/gallery/results/06_signal_tools.png +0 -0
- glplot-0.1.6/examples/gallery/results/07_projected_3d_cloud.png +0 -0
- glplot-0.1.6/examples/gallery/results/08_vector_field_quiver.png +0 -0
- glplot-0.1.6/examples/gallery/results/09_large_matrix_heatmap.png +0 -0
- glplot-0.1.6/examples/gallery/results/10_massive_hist2d_density.png +0 -0
- glplot-0.1.6/examples/gallery/results/11_contour_pcolormesh_field.png +0 -0
- glplot-0.1.6/examples/gallery/results/12_surface_wireframe_bar3d.png +0 -0
- glplot-0.1.6/examples/gallery/results/13_volumetric_nebula.png +0 -0
- glplot-0.1.6/examples/gallery/results/14_bar3d_hex_box_city.png +0 -0
- glplot-0.1.6/examples/gallery/results/15_vector_field_3d.png +0 -0
- glplot-0.1.6/examples/gallery/results/16_ssao_comparison.png +0 -0
- glplot-0.1.6/examples/gallery/results/17_square_bars3d.png +0 -0
- glplot-0.1.6/examples/gallery/results/18_hex_bars3d.png +0 -0
- glplot-0.1.6/examples/gallery/results/19_turbulent_vector_field_3d.png +0 -0
- glplot-0.1.6/examples/gallery/results/20_categorical_bar_and_spines.png +0 -0
- glplot-0.1.6/examples/gallery/results/21_date_axis_and_text_bbox.png +0 -0
- glplot-0.1.6/examples/gallery/results/22_log_scale_plots.png +0 -0
- glplot-0.1.6/examples/gallery/results/23_symlog_scale.png +0 -0
- glplot-0.1.6/examples/gallery/results/24_log_scale_bar_chart.png +0 -0
- glplot-0.1.6/examples/gallery/results/25_log_scale_contourf.png +0 -0
- glplot-0.1.6/examples/gallery/results/26_logit_scale.png +0 -0
- glplot-0.1.6/examples/gallery/results/27_inset_axes_image.png +0 -0
- glplot-0.1.6/examples/gallery/run_gallery.py +0 -39
- glplot-0.1.6/examples/showcase/01_colorful_particles_2d.py +0 -33
- glplot-0.1.6/examples/showcase/02_mandelbrot_zoom_2d.py +0 -50
- glplot-0.1.6/examples/showcase/03_spinning_torus_3d.py +0 -36
- glplot-0.1.6/examples/showcase/04_cosmic_sphere_3d.py +0 -45
- glplot-0.1.6/examples/showcase/README.md +0 -207
- glplot-0.1.6/examples/verify_polyline_cmap.py +0 -36
- glplot-0.1.6/glplot/utils/__init__.py +0 -0
- glplot-0.1.6/paper.md +0 -112
- glplot-0.1.6/plot_1784808407.png +0 -0
- glplot-0.1.6/scratch/check_gl_limits.py +0 -36
- glplot-0.1.6/scratch/check_runtime_math.py +0 -41
- glplot-0.1.6/scratch/diag_view.py +0 -62
- glplot-0.1.6/scratch/smoke_test.py +0 -24
- glplot-0.1.6/scratch/test_asymmetric_projection.py +0 -82
- glplot-0.1.6/scratch/test_autoscale_all.py +0 -38
- glplot-0.1.6/scratch/test_modular_export.py +0 -35
- glplot-0.1.6/tests/verify_blending_extension.py +0 -50
- glplot-0.1.6/tests/verify_density.py +0 -28
- glplot-0.1.6/tests/verify_headless.py +0 -28
- glplot-0.1.6/tests/verify_phase4.py +0 -34
- glplot-0.1.6/tests/verify_phase5_density.py +0 -45
- glplot-0.1.6/tools/README.md +0 -176
- glplot-0.1.6/tools/check_gl_capabilities.py +0 -107
- glplot-0.1.6/tools/diagnose_camera_state.py +0 -126
- glplot-0.1.6/tools/validate_runtime_math.py +0 -126
- {glplot-0.1.6 → glplot-0.1.7}/CHANGELOG.md +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/CITATION.cff +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/LICENSE +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/glplot/__main__.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/glplot/anim/__init__.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/glplot/anim/applier.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/glplot/anim/primitives.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/glplot/anim/processes.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/glplot/backend.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/glplot/core/__init__.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/glplot/core/layout.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/glplot/core/legacy.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/glplot/core/panel.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/glplot/gui/__init__.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/glplot/gui/actions.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/glplot/gui/app.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/glplot/gui/clipboard.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/glplot/gui/commands.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/glplot/gui/dataio.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/glplot/gui/datasets.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/glplot/gui/expressions.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/glplot/gui/fuzzy.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/glplot/gui/history.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/glplot/gui/icons.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/glplot/gui/keys.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/glplot/gui/layerops.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/glplot/gui/layerops3d.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/glplot/gui/mathops.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/glplot/gui/panels/__init__.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/glplot/gui/panels/base.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/glplot/gui/panels/data_editor.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/glplot/gui/panels/dynamics.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/glplot/gui/panels/functions.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/glplot/gui/panels/help.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/glplot/gui/panels/mathlab.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/glplot/gui/panels/palette.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/glplot/gui/panels/pipeline.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/glplot/gui/panels/presentation.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/glplot/gui/panels/scene.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/glplot/gui/panels/selection.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/glplot/gui/panels/style.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/glplot/gui/panels/timeline.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/glplot/gui/panels/view3d.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/glplot/gui/pipeline.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/glplot/gui/theme.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/glplot/gui/widgets.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/glplot/managers/__init__.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/glplot/options.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/glplot/renderers/__init__.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/glplot/renderers/axis.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/glplot/renderers/base.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/glplot/renderers/exact.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/glplot/renderers/fractal.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/glplot/renderers/geometry3d.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/glplot/renderers/interaction.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/glplot/renderers/legend.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/glplot/renderers/polyline.py +0 -0
- {glplot-0.1.6/glplot/scratch → glplot-0.1.7/glplot/utils}/__init__.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/glplot/utils/blending.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/glplot/utils/export.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/glplot/utils/mpl_bridge.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/glplot/utils/mpl_process.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/glplot/utils/scale.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/tests/conftest.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_anim_applier.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_anim_export.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_anim_primitives.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_anim_processes.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_animation_api.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_animation_integration.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_axes.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_axes3d.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_blending_3d.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_camera3d.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_compositing_3d.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_compositing_api.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_dataio.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_density_tint.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_edge_cases.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_effects_post.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_encodings.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_engine.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_fractal.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_generators3d.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_generators3d_extra.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_gui_actions.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_gui_annotate.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_gui_clipboard.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_gui_commands.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_gui_data_editor.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_gui_datasets.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_gui_dynamics.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_gui_engine_integration.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_gui_expressions.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_gui_fields.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_gui_fuzzy.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_gui_history.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_gui_import_safety.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_gui_impostor_alignment.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_gui_keyboard_capture.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_gui_keys.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_gui_layer_colormaps.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_gui_legend.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_gui_mathlab.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_gui_mathops.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_gui_pipeline.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_gui_regression_r2.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_gui_scene_delete.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_gui_scene_order.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_gui_styles.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_gui_timeline_panel.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_helpers.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_impostor_scatter_fidelity.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_layerops3d.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_mpl_compat_3d.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_mpl_parity_surface.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_mpl_process.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_objects3d_preview.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_outline.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_performance_benchmarks.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_plot_style_api.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_pyplot_3d.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_selection_model.py +0 -0
- {glplot-0.1.6 → glplot-0.1.7}/tests/test_timeline.py +0 -0
|
@@ -63,6 +63,10 @@ imgui.ini
|
|
|
63
63
|
*.temp
|
|
64
64
|
.scratch/
|
|
65
65
|
|
|
66
|
+
# Benchmark comparison output (regenerated locally, not referenced by any doc;
|
|
67
|
+
# unlike examples/gallery/results, which IS embedded in README.md and must stay tracked)
|
|
68
|
+
examples/benchmark/results/
|
|
69
|
+
|
|
66
70
|
# Claude Code (local settings only, keep agents/)
|
|
67
71
|
.claude/settings.json
|
|
68
72
|
.claude/settings.local.json
|
glplot-0.1.7/PKG-INFO
ADDED
|
@@ -0,0 +1,576 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: glplot
|
|
3
|
+
Version: 0.1.7
|
|
4
|
+
Summary: High-performance OpenGL plotting library for Python
|
|
5
|
+
Project-URL: Homepage, https://github.com/AkarisDimitry/GLPlot
|
|
6
|
+
Project-URL: Repository, https://github.com/AkarisDimitry/GLPlot
|
|
7
|
+
Project-URL: Issues, https://github.com/AkarisDimitry/GLPlot/issues
|
|
8
|
+
Author-email: Juan Manuel Lombardi <lombardi@fhi-berlin.mpg.de>
|
|
9
|
+
License: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: gpu,opengl,plotting,scientific plotting,visualization
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Intended Audience :: Science/Research
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Operating System :: OS Independent
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
+
Classifier: Topic :: Scientific/Engineering :: Visualization
|
|
23
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
24
|
+
Requires-Python: >=3.9
|
|
25
|
+
Requires-Dist: glfw>=2.5
|
|
26
|
+
Requires-Dist: imgui[glfw]>=2.0
|
|
27
|
+
Requires-Dist: matplotlib>=3.6
|
|
28
|
+
Requires-Dist: numpy>=1.23
|
|
29
|
+
Requires-Dist: pyopengl>=3.1.6
|
|
30
|
+
Requires-Dist: scipy>=1.9
|
|
31
|
+
Provides-Extra: dev
|
|
32
|
+
Requires-Dist: build>=1.0; extra == 'dev'
|
|
33
|
+
Requires-Dist: pytest-cov>=4.0; extra == 'dev'
|
|
34
|
+
Requires-Dist: pytest-mock>=3.10; extra == 'dev'
|
|
35
|
+
Requires-Dist: pytest>=7.0; extra == 'dev'
|
|
36
|
+
Requires-Dist: twine>=4.0; extra == 'dev'
|
|
37
|
+
Provides-Extra: test
|
|
38
|
+
Requires-Dist: pytest-cov>=4.0; extra == 'test'
|
|
39
|
+
Requires-Dist: pytest-mock>=3.10; extra == 'test'
|
|
40
|
+
Requires-Dist: pytest>=7.0; extra == 'test'
|
|
41
|
+
Description-Content-Type: text/markdown
|
|
42
|
+
|
|
43
|
+
# GLPlot: GPU-Accelerated Plotting for Python
|
|
44
|
+
|
|
45
|
+
[](https://github.com/AkarisDimitry/GLPlot/actions/workflows/tests.yml)
|
|
46
|
+
[](https://github.com/AkarisDimitry/GLPlot/actions/workflows/lint.yml)
|
|
47
|
+
[](https://github.com/AkarisDimitry/GLPlot/actions/workflows/build.yml)
|
|
48
|
+
[](LICENSE)
|
|
49
|
+
[](pyproject.toml)
|
|
50
|
+
|
|
51
|
+
GLPlot is a Python plotting library with a Matplotlib-like API that renders on the GPU
|
|
52
|
+
through OpenGL instead of the CPU. Plots that make Matplotlib chug — millions of points,
|
|
53
|
+
dense line families, large 3D scenes — stay interactive: smooth pan, zoom, and rotation,
|
|
54
|
+
even at that scale. If you already know `plt.plot()` / `plt.scatter()`, most of what you
|
|
55
|
+
know carries over directly.
|
|
56
|
+
|
|
57
|
+
## Install
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
pip install glplot
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
or from source:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
git clone https://github.com/AkarisDimitry/GLPlot.git
|
|
67
|
+
cd GLPlot
|
|
68
|
+
pip install -e .
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Requires Python 3.9+. Core dependencies: numpy, scipy, matplotlib, glfw, PyOpenGL,
|
|
72
|
+
`imgui[glfw]` (for the on-screen control panel).
|
|
73
|
+
|
|
74
|
+
## 30-second example
|
|
75
|
+
|
|
76
|
+
```python
|
|
77
|
+
import numpy as np
|
|
78
|
+
import glplot.pyplot as plt
|
|
79
|
+
|
|
80
|
+
x = np.linspace(0, 10, 100)
|
|
81
|
+
|
|
82
|
+
plt.figure("My Plot", figsize=(8, 5))
|
|
83
|
+
plt.plot(x, np.sin(x), "r-", lw=2, label="sin(x)")
|
|
84
|
+
plt.scatter(x[::10], np.sin(x[::10]), c="blue", s=20)
|
|
85
|
+
plt.xlabel("x")
|
|
86
|
+
plt.ylabel("y")
|
|
87
|
+
plt.legend()
|
|
88
|
+
plt.show()
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
That's it — a real window opens, fully interactive (pan/zoom/rotate) from the first frame.
|
|
92
|
+
|
|
93
|
+
## Interactive Examples Gallery (Click any figure to view code)
|
|
94
|
+
|
|
95
|
+
Explore 2D plots, 3D scenes, and real-time animations. **Click on any figure or title below to expand its full Python code.**
|
|
96
|
+
|
|
97
|
+
### 📊 2D Visualizations
|
|
98
|
+
|
|
99
|
+
<details>
|
|
100
|
+
<summary>
|
|
101
|
+
<img src="examples/gallery/results/02_scatter_fill.png" alt="10M-point spiral scatter" width="650"/>
|
|
102
|
+
<br><b>🔍 Click to view code: 10-Million Point Spiral Scatter (<code>02_scatter_fill.py</code>)</b>
|
|
103
|
+
</summary>
|
|
104
|
+
|
|
105
|
+
```python
|
|
106
|
+
import numpy as np
|
|
107
|
+
import glplot.pyplot as plt
|
|
108
|
+
|
|
109
|
+
rng = np.random.default_rng(4)
|
|
110
|
+
n = 10_000_000
|
|
111
|
+
theta = rng.uniform(0, 18 * np.pi, n)
|
|
112
|
+
radius = 0.025 * theta + rng.gamma(1.5, 0.006, n)
|
|
113
|
+
x_pc = radius * np.cos(theta) + rng.normal(scale=0.012, size=n)
|
|
114
|
+
y_pc = radius * np.sin(theta) + rng.normal(scale=0.012, size=n)
|
|
115
|
+
formation_phase = theta + 6.0 * radius # proxy for age along the spiral arm
|
|
116
|
+
|
|
117
|
+
plt.figure("Simulated Spiral Star Field", figsize=(9, 6))
|
|
118
|
+
plt.scatter(x_pc, y_pc, c=formation_phase, cmap="turbo", s=1.5, alpha=0.72)
|
|
119
|
+
plt.title(f"Simulated stellar density along a spiral arm (N = {n:,} stars)")
|
|
120
|
+
plt.xlabel("x (pc)")
|
|
121
|
+
plt.ylabel("y (pc)")
|
|
122
|
+
plt.show()
|
|
123
|
+
```
|
|
124
|
+
</details>
|
|
125
|
+
|
|
126
|
+
<details>
|
|
127
|
+
<summary>
|
|
128
|
+
<img src="examples/gallery/results/10_massive_hist2d_density.png" alt="10M-sample 2D density histogram" width="650"/>
|
|
129
|
+
<br><b>🔍 Click to view code: 10M-Sample 2D Density Histogram (<code>10_massive_hist2d_density.py</code>)</b>
|
|
130
|
+
</summary>
|
|
131
|
+
|
|
132
|
+
```python
|
|
133
|
+
import numpy as np
|
|
134
|
+
import glplot.pyplot as plt
|
|
135
|
+
|
|
136
|
+
rng = np.random.default_rng(123)
|
|
137
|
+
n = 10_000_000
|
|
138
|
+
theta = rng.uniform(0, 2 * np.pi, n)
|
|
139
|
+
r = rng.gamma(shape=2.2, scale=0.8, size=n)
|
|
140
|
+
mm_per_unit = 10.0
|
|
141
|
+
x = mm_per_unit * (r * np.cos(theta) + rng.normal(scale=0.08, size=n))
|
|
142
|
+
y = mm_per_unit * (r * np.sin(theta) + rng.normal(scale=0.08, size=n))
|
|
143
|
+
|
|
144
|
+
plt.figure("Detector Impact Density", figsize=(8, 6))
|
|
145
|
+
lim = 45.0
|
|
146
|
+
plt.hist2d(
|
|
147
|
+
x, y,
|
|
148
|
+
bins=170,
|
|
149
|
+
range=[[-lim, lim], [-lim, lim]],
|
|
150
|
+
cmap="plasma",
|
|
151
|
+
s=40.0,
|
|
152
|
+
label=f"{n:,} hits",
|
|
153
|
+
)
|
|
154
|
+
plt.title(f"{n:,}-hit density map on detector plane")
|
|
155
|
+
plt.xlabel("x (mm)")
|
|
156
|
+
plt.ylabel("y (mm)")
|
|
157
|
+
plt.legend()
|
|
158
|
+
plt.show()
|
|
159
|
+
```
|
|
160
|
+
</details>
|
|
161
|
+
|
|
162
|
+
<details>
|
|
163
|
+
<summary>
|
|
164
|
+
<img src="examples/gallery/results/01_line_plot.png" alt="10,072-line oscilloscope ensemble" width="650"/>
|
|
165
|
+
<br><b>🔍 Click to view code: 10,072-Line Oscilloscope Ensemble (<code>01_line_plot.py</code>)</b>
|
|
166
|
+
</summary>
|
|
167
|
+
|
|
168
|
+
```python
|
|
169
|
+
import colorsys
|
|
170
|
+
import numpy as np
|
|
171
|
+
import glplot.pyplot as plt
|
|
172
|
+
|
|
173
|
+
def chalk_color(hue: float, rng: np.random.Generator) -> tuple:
|
|
174
|
+
sat = rng.uniform(0.22, 0.42)
|
|
175
|
+
val = rng.uniform(0.90, 1.0)
|
|
176
|
+
return colorsys.hsv_to_rgb(hue % 1.0, sat, val)
|
|
177
|
+
|
|
178
|
+
rng = np.random.default_rng(101)
|
|
179
|
+
n_channels = 10_072
|
|
180
|
+
n_points = 180
|
|
181
|
+
t = np.linspace(0, 40 * np.pi, n_points)
|
|
182
|
+
t_ms = t * (50.0 / (40 * np.pi))
|
|
183
|
+
stimulus = np.sin(t) + 0.35 * np.sin(2.7 * t)
|
|
184
|
+
|
|
185
|
+
plt.figure("Oscilloscope Ensemble", figsize=(9, 5))
|
|
186
|
+
plt.plot_style("chalk", layers=False)
|
|
187
|
+
|
|
188
|
+
frac = np.linspace(0.0, 1.0, n_channels)
|
|
189
|
+
hues = (rng.uniform(0, 1) + frac + rng.uniform(-0.02, 0.02, n_channels)) % 1.0
|
|
190
|
+
|
|
191
|
+
for i in range(n_channels):
|
|
192
|
+
t_frac = frac[i]
|
|
193
|
+
phase = rng.uniform(0, 2 * np.pi)
|
|
194
|
+
amp = 0.12 + 0.781 * t_frac
|
|
195
|
+
freq = 1.1 + 0.852 * t_frac
|
|
196
|
+
offset = 3.195 * t_frac
|
|
197
|
+
channel = stimulus + amp * np.sin(freq * t + phase)
|
|
198
|
+
color = chalk_color(hues[i], rng)
|
|
199
|
+
plt.plot(t_ms, channel + offset, color=(*color, 0.35), lw=0.5)
|
|
200
|
+
|
|
201
|
+
plt.plot(t_ms, stimulus + 0.7, color=(0.95, 0.94, 0.90, 1.0), lw=3.0, label="Reference")
|
|
202
|
+
plt.xlabel("Time (ms)")
|
|
203
|
+
plt.ylabel("Amplitude")
|
|
204
|
+
plt.title(f"Traces from {n_channels} oscillator channels")
|
|
205
|
+
plt.legend()
|
|
206
|
+
plt.show()
|
|
207
|
+
```
|
|
208
|
+
</details>
|
|
209
|
+
|
|
210
|
+
### 🪐 3D Visualizations
|
|
211
|
+
|
|
212
|
+
<details>
|
|
213
|
+
<summary>
|
|
214
|
+
<img src="examples/gallery/results/07_projected_3d_cloud.png" alt="1M-point 3D Point Cloud" width="650"/>
|
|
215
|
+
<br><b>🔍 Click to view code: 1M-Point Circumstellar Dust Halo (<code>07_projected_3d_cloud.py</code>)</b>
|
|
216
|
+
</summary>
|
|
217
|
+
|
|
218
|
+
```python
|
|
219
|
+
import numpy as np
|
|
220
|
+
import glplot.pyplot as plt
|
|
221
|
+
|
|
222
|
+
rng = np.random.default_rng(77)
|
|
223
|
+
n = 1_000_000
|
|
224
|
+
sigma = 42.0
|
|
225
|
+
outer_radius = 2.5 * sigma
|
|
226
|
+
n_gen = 1_140_000
|
|
227
|
+
x = rng.normal(0.0, sigma, n_gen)
|
|
228
|
+
y = rng.normal(0.0, sigma, n_gen)
|
|
229
|
+
z = rng.normal(0.0, sigma, n_gen)
|
|
230
|
+
inside = (x**2 + y**2 + z**2) < outer_radius**2
|
|
231
|
+
x, y, z = x[inside][:n], y[inside][:n], z[inside][:n]
|
|
232
|
+
|
|
233
|
+
plt.figure("Circumstellar Dust Halo", figsize=(9, 6))
|
|
234
|
+
plt.scatter3d(
|
|
235
|
+
x, y, z,
|
|
236
|
+
c=z,
|
|
237
|
+
cmap="viridis",
|
|
238
|
+
s=1.1,
|
|
239
|
+
alpha=0.75,
|
|
240
|
+
elev=22,
|
|
241
|
+
azim=-42,
|
|
242
|
+
label=f"{n:,} grains",
|
|
243
|
+
)
|
|
244
|
+
plt.title(f"Simulated circumstellar dust halo ({n:,} grains)")
|
|
245
|
+
plt.xlabel("x (AU)")
|
|
246
|
+
plt.ylabel("y (AU)")
|
|
247
|
+
plt.zlabel("z (AU)")
|
|
248
|
+
plt.legend()
|
|
249
|
+
plt.show()
|
|
250
|
+
```
|
|
251
|
+
</details>
|
|
252
|
+
|
|
253
|
+
<details>
|
|
254
|
+
<summary>
|
|
255
|
+
<img src="examples/gallery/results/13_volumetric_nebula.png" alt="1.75M-Point Volumetric Nebula" width="650"/>
|
|
256
|
+
<br><b>🔍 Click to view code: 1.75M-Point Volumetric Nebula (<code>13_volumetric_nebula.py</code>)</b>
|
|
257
|
+
</summary>
|
|
258
|
+
|
|
259
|
+
```python
|
|
260
|
+
import numpy as np
|
|
261
|
+
import glplot.pyplot as plt
|
|
262
|
+
|
|
263
|
+
rng = np.random.default_rng(1313)
|
|
264
|
+
n = 1_750_000
|
|
265
|
+
outer_radius = 3.2
|
|
266
|
+
n_gen = 2_000_000
|
|
267
|
+
theta = rng.uniform(0, 8 * np.pi, n_gen)
|
|
268
|
+
phi = rng.normal(0.0, 0.48, n_gen)
|
|
269
|
+
r = rng.gamma(2.0, 0.8, n_gen)
|
|
270
|
+
inside = r < outer_radius
|
|
271
|
+
theta, phi, r = theta[inside][:n], phi[inside][:n], r[inside][:n]
|
|
272
|
+
arm = rng.integers(0, 4, n) * np.pi / 2
|
|
273
|
+
twist = theta + arm + 0.62 * r
|
|
274
|
+
x = r * np.cos(twist) + rng.normal(scale=0.06, size=n)
|
|
275
|
+
y = r * np.sin(twist) + rng.normal(scale=0.06, size=n)
|
|
276
|
+
z = 0.65 * r * np.sin(phi) + 0.18 * np.sin(theta)
|
|
277
|
+
emission = np.exp(-0.12 * r**2) + 0.28 * np.sin(3 * theta) ** 2
|
|
278
|
+
|
|
279
|
+
plt.figure("Volumetric 3D Nebula", figsize=(9, 6))
|
|
280
|
+
plt.volume3d(
|
|
281
|
+
x, y, z, emission,
|
|
282
|
+
threshold=0.14,
|
|
283
|
+
cmap="magma",
|
|
284
|
+
alpha=0.42,
|
|
285
|
+
s=1.2,
|
|
286
|
+
elev=24,
|
|
287
|
+
azim=-52,
|
|
288
|
+
label=f"{n:,} points",
|
|
289
|
+
)
|
|
290
|
+
plt.title(f"{n:,}-point volumetric emission nebula")
|
|
291
|
+
plt.xlabel("x (ly)")
|
|
292
|
+
plt.ylabel("y (ly)")
|
|
293
|
+
plt.zlabel("z (ly)")
|
|
294
|
+
plt.legend()
|
|
295
|
+
plt.show()
|
|
296
|
+
```
|
|
297
|
+
</details>
|
|
298
|
+
|
|
299
|
+
<details>
|
|
300
|
+
<summary>
|
|
301
|
+
<img src="examples/gallery/results/19_turbulent_vector_field_3d.png" alt="3D Turbulent Vector Field" width="650"/>
|
|
302
|
+
<br><b>🔍 Click to view code: 3D Turbulent Vector Field (<code>19_turbulent_vector_field_3d.py</code>)</b>
|
|
303
|
+
</summary>
|
|
304
|
+
|
|
305
|
+
```python
|
|
306
|
+
import numpy as np
|
|
307
|
+
import glplot.pyplot as plt
|
|
308
|
+
|
|
309
|
+
rng = np.random.default_rng(1919)
|
|
310
|
+
cloud_n = 950_000
|
|
311
|
+
t = rng.uniform(0.0, 18.0 * np.pi, cloud_n)
|
|
312
|
+
shell_raw = rng.gamma(2.2, 0.42, cloud_n)
|
|
313
|
+
shell = 2.0 * np.tanh(shell_raw / 2.0)
|
|
314
|
+
twist = 0.22 * np.sin(2.6 * t) + 0.18 * np.cos(1.4 * t)
|
|
315
|
+
cloud_x = shell * np.sin(t) + 0.28 * np.sin(3.0 * t)
|
|
316
|
+
cloud_y = shell * np.cos(1.17 * t) + 0.32 * np.cos(2.4 * t)
|
|
317
|
+
cloud_z = 0.58 * np.sin(0.52 * t + twist) + 0.32 * shell * np.cos(0.33 * t)
|
|
318
|
+
cloud_energy = np.exp(-0.22 * shell**2) + 0.33 * np.sin(1.7 * t) ** 2
|
|
319
|
+
|
|
320
|
+
plt.figure("Turbulent 3D Flow", figsize=(10, 7), ssao=True)
|
|
321
|
+
plt.volume3d(
|
|
322
|
+
cloud_x, cloud_y, cloud_z, cloud_energy,
|
|
323
|
+
threshold=0.22,
|
|
324
|
+
cmap="inferno",
|
|
325
|
+
alpha=0.17,
|
|
326
|
+
s=0.72,
|
|
327
|
+
elev=27,
|
|
328
|
+
azim=-49,
|
|
329
|
+
label=f"{cloud_n:,} volumetric samples",
|
|
330
|
+
)
|
|
331
|
+
plt.title("Massive 3D turbulent swirl")
|
|
332
|
+
plt.xlabel("x")
|
|
333
|
+
plt.ylabel("y")
|
|
334
|
+
plt.zlabel("z")
|
|
335
|
+
plt.legend()
|
|
336
|
+
plt.show()
|
|
337
|
+
```
|
|
338
|
+
</details>
|
|
339
|
+
|
|
340
|
+
### 🎬 Animated Visualizations
|
|
341
|
+
|
|
342
|
+
<details>
|
|
343
|
+
<summary>
|
|
344
|
+
<img src="examples/gallery/results/28_chladni_wave_animation.gif" alt="Chladni wave animation" width="650"/>
|
|
345
|
+
<br><b>🔍 Click to view code: Animated Standing-Wave Interference (<code>28_chladni_wave_animation.py</code>)</b>
|
|
346
|
+
</summary>
|
|
347
|
+
|
|
348
|
+
```python
|
|
349
|
+
import numpy as np
|
|
350
|
+
import glplot.animation as animation
|
|
351
|
+
import glplot.pyplot as plt
|
|
352
|
+
|
|
353
|
+
N = 360
|
|
354
|
+
x = np.linspace(-1.0, 1.0, N)
|
|
355
|
+
y = np.linspace(-1.0, 1.0, N)
|
|
356
|
+
X, Y = np.meshgrid(x, y)
|
|
357
|
+
FRAMES = 54
|
|
358
|
+
|
|
359
|
+
def chladni_field(m: float, n: float) -> np.ndarray:
|
|
360
|
+
return np.sin(m * np.pi * X) * np.cos(n * np.pi * Y) - np.sin(n * np.pi * X) * np.cos(m * np.pi * Y)
|
|
361
|
+
|
|
362
|
+
def mode_pair(frame: int) -> tuple:
|
|
363
|
+
t = frame / FRAMES
|
|
364
|
+
m = 2.2 + 4.3 * (0.5 - 0.5 * np.cos(2 * np.pi * t))
|
|
365
|
+
n = 3.1 + 3.6 * (0.5 - 0.5 * np.cos(2 * np.pi * t * 1.5 + 1.1))
|
|
366
|
+
return m, n
|
|
367
|
+
|
|
368
|
+
def zoom_span(frame: int) -> float:
|
|
369
|
+
t = frame / FRAMES
|
|
370
|
+
return 0.75 - 0.35 * np.cos(2 * np.pi * t)
|
|
371
|
+
|
|
372
|
+
fig = plt.figure("Animated Standing-Wave Interference", figsize=(7.8, 6.2))
|
|
373
|
+
plt.plot_style("blueprint")
|
|
374
|
+
|
|
375
|
+
def update(frame: int):
|
|
376
|
+
m, n = mode_pair(frame)
|
|
377
|
+
span = zoom_span(frame)
|
|
378
|
+
Z = chladni_field(m, n)
|
|
379
|
+
plt.cla()
|
|
380
|
+
plt.imshow(Z, extent=(-1, 1, -1, 1), origin="lower", cmap="RdBu_r", vmin=-1.0, vmax=1.0, aspect="equal")
|
|
381
|
+
plt.xlim(-span, span)
|
|
382
|
+
plt.ylim(-span, span)
|
|
383
|
+
plt.title(f"Standing-wave interference (m={m:.1f}, n={n:.1f})")
|
|
384
|
+
plt.xlabel("x (plate width)")
|
|
385
|
+
plt.ylabel("y (plate width)")
|
|
386
|
+
return []
|
|
387
|
+
|
|
388
|
+
ani = animation.FuncAnimation(fig, update, frames=FRAMES, interval=42)
|
|
389
|
+
ani.save("chladni_wave_animation.gif", fps=20)
|
|
390
|
+
plt.show()
|
|
391
|
+
```
|
|
392
|
+
</details>
|
|
393
|
+
|
|
394
|
+
<details>
|
|
395
|
+
<summary>
|
|
396
|
+
<img src="examples/gallery/animations/results/03_spectrum_analyzer_bars.gif" alt="Audio spectrum analyzer bars" width="650"/>
|
|
397
|
+
<br><b>🔍 Click to view code: Real-Time Audio Spectrum Analyzer (<code>03_spectrum_analyzer_bars.py</code>)</b>
|
|
398
|
+
</summary>
|
|
399
|
+
|
|
400
|
+
```python
|
|
401
|
+
import numpy as np
|
|
402
|
+
import glplot.animation as animation
|
|
403
|
+
import glplot.pyplot as plt
|
|
404
|
+
|
|
405
|
+
N_BANDS = 64
|
|
406
|
+
FRAMES = 84
|
|
407
|
+
band_x = np.arange(N_BANDS)
|
|
408
|
+
|
|
409
|
+
fig = plt.figure("Audio Spectrum Analyzer", figsize=(9, 5))
|
|
410
|
+
|
|
411
|
+
def update(frame: int):
|
|
412
|
+
t = frame / FRAMES
|
|
413
|
+
levels = -25.0 + 18.0 * np.sin(np.linspace(0.2, 4.0 * np.pi, N_BANDS) + 2.0 * np.pi * t)
|
|
414
|
+
plt.cla()
|
|
415
|
+
plt.bar(band_x, levels, color="tab:cyan", alpha=0.85)
|
|
416
|
+
plt.ylim(-60, 0)
|
|
417
|
+
plt.title("Real-Time 64-Band Spectrum Analyzer")
|
|
418
|
+
plt.xlabel("Frequency Band")
|
|
419
|
+
plt.ylabel("Power (dBFS)")
|
|
420
|
+
return []
|
|
421
|
+
|
|
422
|
+
ani = animation.FuncAnimation(fig, update, frames=FRAMES, interval=33)
|
|
423
|
+
ani.save("spectrum_analyzer.gif", fps=30)
|
|
424
|
+
plt.show()
|
|
425
|
+
```
|
|
426
|
+
</details>
|
|
427
|
+
|
|
428
|
+
<details>
|
|
429
|
+
<summary>
|
|
430
|
+
<img src="examples/gallery/animations/results/01_orbiting_star_cluster.gif" alt="Orbiting star cluster" width="650"/>
|
|
431
|
+
<br><b>🔍 Click to view code: Differential Keplerian Star Cluster (<code>01_orbiting_star_cluster.py</code>)</b>
|
|
432
|
+
</summary>
|
|
433
|
+
|
|
434
|
+
```python
|
|
435
|
+
import numpy as np
|
|
436
|
+
import glplot.animation as animation
|
|
437
|
+
import glplot.pyplot as plt
|
|
438
|
+
|
|
439
|
+
N_STARS = 20_000
|
|
440
|
+
FRAMES = 80
|
|
441
|
+
LIM = 6.8
|
|
442
|
+
|
|
443
|
+
rng = np.random.default_rng(42)
|
|
444
|
+
radius = rng.exponential(scale=1.35, size=N_STARS) + 0.10
|
|
445
|
+
arm_id = rng.integers(0, 3, N_STARS)
|
|
446
|
+
theta0 = arm_id * (2.0 * np.pi / 3) + 1.65 * np.log(radius / 0.10)
|
|
447
|
+
omega = 1.35 / np.sqrt(radius + 0.30)
|
|
448
|
+
|
|
449
|
+
fig = plt.figure("Orbiting Star Cluster", figsize=(8, 8))
|
|
450
|
+
|
|
451
|
+
def update(frame: int):
|
|
452
|
+
t = frame * 0.08
|
|
453
|
+
theta = theta0 + omega * t
|
|
454
|
+
x = radius * np.cos(theta)
|
|
455
|
+
y = radius * np.sin(theta)
|
|
456
|
+
plt.cla()
|
|
457
|
+
plt.scatter(x, y, c=radius, cmap="plasma", s=1.2, alpha=0.8)
|
|
458
|
+
plt.xlim(-LIM, LIM)
|
|
459
|
+
plt.ylim(-LIM, LIM)
|
|
460
|
+
plt.title(f"Differential Keplerian rotation ({N_STARS:,} stars)")
|
|
461
|
+
return []
|
|
462
|
+
|
|
463
|
+
ani = animation.FuncAnimation(fig, update, frames=FRAMES, interval=40)
|
|
464
|
+
ani.save("star_cluster.gif", fps=25)
|
|
465
|
+
plt.show()
|
|
466
|
+
```
|
|
467
|
+
</details>
|
|
468
|
+
|
|
469
|
+
**All of the above render at 60+ FPS** with interactive panning, zooming, and rotation, regardless of point count. Discover more in the [example gallery](examples/gallery/README.md) (28 static scripts) and the [animated gallery](examples/gallery/animations/README.md) (15 animated scripts).
|
|
470
|
+
|
|
471
|
+
## Features
|
|
472
|
+
|
|
473
|
+
- **Matplotlib-compatible API** — `plot`, `scatter`, `bar`, `hist`, `hist2d`, `imshow`,
|
|
474
|
+
`contour`/`contourf`, `quiver`, format strings (`"r-o"`, `"b--"`), and more
|
|
475
|
+
- **Millions of points, still interactive** — GPU instancing and density accumulation
|
|
476
|
+
instead of CPU-side geometry construction
|
|
477
|
+
- **Full 2D/3D** — lines, scatter, filled regions, bars, histograms, matrices, surfaces,
|
|
478
|
+
wireframes, 3D bars, vector fields, with SSAO depth shading in 3D
|
|
479
|
+
- **Real multi-panel subplots** — `plt.subplots()`, per-panel interaction
|
|
480
|
+
- **Animation** — `glplot.animation.FuncAnimation`/`ArtistAnimation`, exportable to GIF/video
|
|
481
|
+
- **A live control panel** — `python -m glplot` opens a workstation for editing a scene,
|
|
482
|
+
its layers, and its styling interactively, with undo history
|
|
483
|
+
- **Numerically stable at extreme zoom** — double-precision, viewport-relative coordinate
|
|
484
|
+
transforms avoid the jitter that single-precision GPU pipelines show at large offsets
|
|
485
|
+
|
|
486
|
+
## Quick Reference Recipes
|
|
487
|
+
|
|
488
|
+
**A million lines at once (`plot_lines`)**
|
|
489
|
+
|
|
490
|
+
Ordinary plotting draws each line as CPU-generated geometry — a million calls to `plot()`
|
|
491
|
+
would build a million separate meshes. `plot_lines` instead uploads each line as an
|
|
492
|
+
`(a, b)` coefficient pair and lets the GPU work out what's visible:
|
|
493
|
+
|
|
494
|
+
```python
|
|
495
|
+
import numpy as np
|
|
496
|
+
import glplot.pyplot as plt
|
|
497
|
+
|
|
498
|
+
n = 1_000_000
|
|
499
|
+
a = np.random.randn(n)
|
|
500
|
+
b = np.random.randn(n)
|
|
501
|
+
|
|
502
|
+
plt.figure("Density")
|
|
503
|
+
plt.plot_lines(a, b, x_range=(-2, 2))
|
|
504
|
+
plt.show(density=True)
|
|
505
|
+
```
|
|
506
|
+
|
|
507
|
+
## How it compares
|
|
508
|
+
|
|
509
|
+
| Feature | GLPlot | Matplotlib | Plotly | Datashader | VisPy |
|
|
510
|
+
|---|---|---|---|---|---|
|
|
511
|
+
| GPU acceleration | ✓ (OpenGL) | ✗ | ✗ | ✓ | ✓ |
|
|
512
|
+
| Matplotlib-style API | ✓ | ✓ | ✗ | ✗ | ✗ |
|
|
513
|
+
| Millions of points, interactive | ✓ | ✗ | Limited | ✓ | ✓ |
|
|
514
|
+
| Interactive 3D | ✓ | Limited | ✓ | Limited | ✓ |
|
|
515
|
+
| Density visualization | ✓ (HDR) | Basic | Limited | ✓ | ✗ |
|
|
516
|
+
| Precision at extreme zoom | ✓ (double precision) | ✓ | Basic | ✓ | ✗ |
|
|
517
|
+
|
|
518
|
+
GLPlot sits between "familiar API, CPU-bound" (Matplotlib) and "GPU-fast, low-level"
|
|
519
|
+
(VisPy): a Matplotlib-shaped surface backed by a GPU renderer.
|
|
520
|
+
|
|
521
|
+
## Rendering architecture
|
|
522
|
+
|
|
523
|
+
GLPlot runs two rendering pipelines — one for 2D primitives (lines, scatter, density) and
|
|
524
|
+
one for 3D geometry (bars, surfaces, wireframes, `scatter3d`) — both driven from the CPU
|
|
525
|
+
but doing their actual work on the GPU. `glReadPixels` is only ever called for export; the
|
|
526
|
+
interactive path never reads pixels back to the CPU.
|
|
527
|
+
|
|
528
|
+

|
|
529
|
+
|
|
530
|
+
See [GLPlot_Architecture_and_Mathematical_Formulation.md](GLPlot_Architecture_and_Mathematical_Formulation.md)
|
|
531
|
+
for the full derivation of each stage, including the density-accumulation math and the
|
|
532
|
+
viewport-relative projection that keeps zoom numerically stable.
|
|
533
|
+
|
|
534
|
+
## Testing
|
|
535
|
+
|
|
536
|
+
```bash
|
|
537
|
+
pytest # run everything
|
|
538
|
+
pytest --cov=glplot --cov-report=html # with coverage
|
|
539
|
+
pytest tests/test_pyplot.py::test_plot_accepts_y_only_and_returns_artists # one test
|
|
540
|
+
```
|
|
541
|
+
|
|
542
|
+
6,800+ tests, run fully headless (no window is ever displayed) so they work in CI. The
|
|
543
|
+
matrix covers Python 3.9–3.12 on Ubuntu, macOS, and Windows; `black`, `isort`, and `flake8`
|
|
544
|
+
are enforced on every push. See `examples/benchmark/` for reproducible performance
|
|
545
|
+
comparisons against Matplotlib, VisPy, fastplotlib, Datashader, and hvPlot, and `tools/`
|
|
546
|
+
for GPU/environment diagnostics.
|
|
547
|
+
|
|
548
|
+
## Documentation
|
|
549
|
+
|
|
550
|
+
- API reference: docstrings in `glplot.pyplot`, or the built docs — see [docs/README.md](docs/README.md)
|
|
551
|
+
- Architecture: [GLPlot_Architecture_and_Mathematical_Formulation.md](GLPlot_Architecture_and_Mathematical_Formulation.md)
|
|
552
|
+
- Dev tools: [tools/README.md](tools/README.md)
|
|
553
|
+
- Contributing: [CONTRIBUTING.md](CONTRIBUTING.md) · Code of conduct: [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md)
|
|
554
|
+
|
|
555
|
+
## Citation
|
|
556
|
+
|
|
557
|
+
```bibtex
|
|
558
|
+
@software{lombardi2026glplot,
|
|
559
|
+
title={GLPlot: High-Performance GPU-Accelerated Plotting Library for Python},
|
|
560
|
+
author={Lombardi, Juan Manuel},
|
|
561
|
+
year={2026},
|
|
562
|
+
url={https://github.com/AkarisDimitry/GLPlot},
|
|
563
|
+
doi={10.5281/zenodo.PLACEHOLDER}
|
|
564
|
+
}
|
|
565
|
+
```
|
|
566
|
+
|
|
567
|
+
See [CITATION.cff](CITATION.cff) for other formats.
|
|
568
|
+
|
|
569
|
+
## License
|
|
570
|
+
|
|
571
|
+
[MIT](LICENSE).
|
|
572
|
+
|
|
573
|
+
## Acknowledgments
|
|
574
|
+
|
|
575
|
+
Built on PyOpenGL, GLFW, NumPy, SciPy, Matplotlib, and Dear ImGui — thanks to those
|
|
576
|
+
communities for the foundations this sits on.
|