plopp 25.6.0__tar.gz → 25.7.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.
- {plopp-25.6.0 → plopp-25.7.0}/.github/workflows/release.yml +2 -46
- {plopp-25.6.0 → plopp-25.7.0}/PKG-INFO +2 -2
- {plopp-25.6.0 → plopp-25.7.0}/README.md +1 -1
- {plopp-25.6.0 → plopp-25.7.0}/docs/gallery/streaming-plot.ipynb +148 -2
- {plopp-25.6.0 → plopp-25.7.0}/docs/plotting/slicer-plot.ipynb +42 -0
- {plopp-25.6.0 → plopp-25.7.0}/docs/plotting/super-plot.ipynb +2 -3
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp/core/graph.py +2 -2
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp/core/helpers.py +1 -1
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp/core/node_class.py +3 -3
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp/graphics/graphicalview.py +1 -1
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp/plotting/common.py +116 -77
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp/plotting/slicer.py +10 -1
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp/plotting/xyplot.py +11 -4
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp/widgets/drawing.py +2 -2
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp/widgets/linesave.py +1 -1
- plopp-25.7.0/src/plopp/widgets/slice.py +186 -0
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp.egg-info/PKG-INFO +2 -2
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp.egg-info/SOURCES.txt +0 -1
- {plopp-25.6.0 → plopp-25.7.0}/tests/core/node_test.py +7 -7
- {plopp-25.6.0 → plopp-25.7.0}/tests/high_level_test.py +2 -2
- {plopp-25.6.0 → plopp-25.7.0}/tests/plotting/plot_1d_test.py +6 -0
- {plopp-25.6.0 → plopp-25.7.0}/tests/plotting/plot_2d_test.py +35 -3
- {plopp-25.6.0 → plopp-25.7.0}/tests/plotting/slicer_test.py +11 -11
- {plopp-25.6.0 → plopp-25.7.0}/tests/plotting/superplot_test.py +4 -6
- {plopp-25.6.0 → plopp-25.7.0}/tests/plotting/xyplot_test.py +13 -5
- {plopp-25.6.0 → plopp-25.7.0}/tests/widgets/slice_test.py +23 -17
- plopp-25.6.0/conda/meta.yaml +0 -60
- plopp-25.6.0/src/plopp/widgets/slice.py +0 -135
- {plopp-25.6.0 → plopp-25.7.0}/.copier-answers.yml +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/.github/dependabot.yml +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/.github/workflows/ci.yml +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/.github/workflows/docs.yml +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/.github/workflows/nightly_at_main.yml +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/.github/workflows/nightly_at_release.yml +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/.github/workflows/python-version-ci +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/.github/workflows/test.yml +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/.github/workflows/unpinned.yml +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/.github/workflows/weekly_windows_macos.yml +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/.gitignore +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/.pre-commit-config.yaml +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/.python-version +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/CODE_OF_CONDUCT.md +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/CONTRIBUTING.md +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/LICENSE +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/MANIFEST.in +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/docs/_static/anaconda-icon.js +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/docs/_static/circle-exclamation.svg +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/docs/_static/custom.css +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/docs/_static/customization/custom-interfaces.png +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/docs/_static/customization/graph-node-tips.png +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/docs/_static/customization/subplots.png +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/docs/_static/customization/tweaking-figures.png +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/docs/_static/favicon.ico +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/docs/_static/gallery/README.txt +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/docs/_static/gallery/peeling-layers-thumbnail.png +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/docs/_static/gallery/scatter3d-with-slider-thumbnail.png +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/docs/_static/gallery/scatter3d-with-threshold-thumbnail.png +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/docs/_static/logo-dark.svg +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/docs/_static/logo-large-dark.svg +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/docs/_static/logo-large.svg +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/docs/_static/logo.svg +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/docs/_static/plotting/image-plot.png +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/docs/_static/plotting/inspector-plot.png +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/docs/_static/plotting/line-plot.png +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/docs/_static/plotting/mesh3d-plot.png +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/docs/_static/plotting/scatter-plot.png +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/docs/_static/plotting/scatter3d-plot.png +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/docs/_static/plotting/slicer-plot.png +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/docs/_static/plotting/super-plot.png +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/docs/_templates/class-template.rst +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/docs/_templates/doc_version.html +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/docs/_templates/module-template.rst +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/docs/_templates/scipp-class-template.rst +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/docs/_templates/scipp-module-template.rst +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/docs/about/index.md +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/docs/api-reference/index.md +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/docs/api-reference/matplotlib.md +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/docs/api-reference/plotly.md +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/docs/api-reference/pythreejs.md +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/docs/conf.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/docs/customization/custom-interfaces.ipynb +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/docs/customization/graph-node-tips.ipynb +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/docs/customization/index.md +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/docs/customization/subplots.ipynb +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/docs/customization/tweaking-figures.ipynb +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/docs/developer/coding-conventions.md +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/docs/developer/dependency-management.md +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/docs/developer/getting-started.md +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/docs/developer/index.md +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/docs/gallery/index.ipynb +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/docs/gallery/interactive-masking.ipynb +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/docs/gallery/masking-a-range.ipynb +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/docs/gallery/nyc-taxi.ipynb +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/docs/gallery/peeling-layers.ipynb +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/docs/gallery/polar-plots.ipynb +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/docs/gallery/rectangle-selection.ipynb +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/docs/gallery/scatter3d-with-slider.ipynb +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/docs/gallery/scatter3d-with-threshold.ipynb +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/docs/gallery/tiled-random-samples.ipynb +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/docs/gallery/updating-scatter.ipynb +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/docs/getting-started/index.md +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/docs/getting-started/installation.md +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/docs/getting-started/numpy-pandas-xarray.ipynb +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/docs/getting-started/overview.ipynb +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/docs/getting-started/saving-figures.ipynb +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/docs/index.md +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/docs/plotting/image-plot.ipynb +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/docs/plotting/index.md +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/docs/plotting/inspector-plot.ipynb +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/docs/plotting/line-plot.ipynb +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/docs/plotting/mesh3d-plot.ipynb +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/docs/plotting/scatter-plot.ipynb +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/docs/plotting/scatter3d-plot.ipynb +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/pyproject.toml +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/requirements/base.in +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/requirements/base.txt +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/requirements/basetest.in +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/requirements/basetest.txt +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/requirements/ci.in +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/requirements/ci.txt +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/requirements/dev.in +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/requirements/dev.txt +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/requirements/docs.in +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/requirements/docs.txt +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/requirements/make_base.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/requirements/mini.in +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/requirements/mini.txt +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/requirements/mypy.in +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/requirements/mypy.txt +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/requirements/nightly.in +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/requirements/nightly.txt +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/requirements/noplotly.in +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/requirements/noplotly.txt +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/requirements/static.in +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/requirements/static.txt +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/requirements/test.in +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/requirements/test.txt +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/requirements/wheels.in +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/requirements/wheels.txt +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/resources/logo-plopp-2022.svg +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/setup.cfg +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp/__init__.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp/backends/__init__.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp/backends/common.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp/backends/matplotlib/__init__.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp/backends/matplotlib/canvas.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp/backends/matplotlib/fast_image.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp/backends/matplotlib/figure.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp/backends/matplotlib/image.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp/backends/matplotlib/line.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp/backends/matplotlib/mesh_image.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp/backends/matplotlib/scatter.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp/backends/matplotlib/tiled.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp/backends/matplotlib/utils.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp/backends/plotly/__init__.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp/backends/plotly/canvas.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp/backends/plotly/figure.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp/backends/plotly/line.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp/backends/pythreejs/__init__.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp/backends/pythreejs/canvas.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp/backends/pythreejs/figure.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp/backends/pythreejs/mesh3d.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp/backends/pythreejs/outline.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp/backends/pythreejs/scatter3d.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp/core/__init__.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp/core/__init__.pyi +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp/core/limits.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp/core/typing.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp/core/utils.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp/core/view.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp/data/__init__.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp/data/examples.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp/data/factory.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp/data/testing.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp/graphics/__init__.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp/graphics/__init__.pyi +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp/graphics/basefig.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp/graphics/bbox.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp/graphics/camera.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp/graphics/colormapper.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp/graphics/figures.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp/graphics/tiled.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp/plotting/__init__.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp/plotting/__init__.pyi +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp/plotting/inspector.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp/plotting/mesh3d.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp/plotting/plot.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp/plotting/scatter.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp/plotting/scatter3d.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp/plotting/superplot.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp/py.typed +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp/utils.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp/widgets/__init__.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp/widgets/__init__.pyi +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp/widgets/box.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp/widgets/checkboxes.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp/widgets/clip3d.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp/widgets/debounce.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp/widgets/style.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp/widgets/toolbar.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp/widgets/tools.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp.egg-info/dependency_links.txt +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp.egg-info/requires.txt +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/src/plopp.egg-info/top_level.txt +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/tests/backends/matplotlib/mpl_image_test.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/tests/backends/matplotlib/mpl_line_test.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/tests/backends/matplotlib/mpl_plot_test.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/tests/backends/matplotlib/mpl_scatter_test.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/tests/backends/matplotlib/mpl_tiled_test.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/tests/backends/plotly/conftest.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/tests/backends/plotly/plotly_line_test.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/tests/backends/pythreejs/pythreejs_canvas_test.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/tests/backends/pythreejs/pythreejs_scatter3d_test.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/tests/conftest.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/tests/core/graph_test.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/tests/core/limits_test.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/tests/core/utils_test.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/tests/graphics/artists_test.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/tests/graphics/canvas_test.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/tests/graphics/colormapper_test.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/tests/graphics/figures_test.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/tests/minimal_plot_test.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/tests/package_test.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/tests/plotting/common_test.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/tests/plotting/inspector_test.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/tests/plotting/mesh3d_test.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/tests/plotting/scatter3d_test.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/tests/plotting/scatter_test.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/tests/widgets/box_test.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/tests/widgets/checkboxes_test.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/tests/widgets/clip3d_test.py +0 -0
- {plopp-25.6.0 → plopp-25.7.0}/tox.ini +0 -0
|
@@ -5,34 +5,7 @@ on:
|
|
|
5
5
|
types: [published]
|
|
6
6
|
workflow_dispatch:
|
|
7
7
|
|
|
8
|
-
defaults:
|
|
9
|
-
run:
|
|
10
|
-
shell: bash -l {0} # required for conda env
|
|
11
|
-
|
|
12
8
|
jobs:
|
|
13
|
-
build_conda:
|
|
14
|
-
name: Conda build
|
|
15
|
-
runs-on: 'ubuntu-24.04'
|
|
16
|
-
|
|
17
|
-
steps:
|
|
18
|
-
- uses: actions/checkout@v4
|
|
19
|
-
with:
|
|
20
|
-
submodules: true
|
|
21
|
-
fetch-depth: 0 # history required so setuptools_scm can determine version
|
|
22
|
-
|
|
23
|
-
- uses: mamba-org/setup-micromamba@v1
|
|
24
|
-
with:
|
|
25
|
-
environment-name: build-env
|
|
26
|
-
create-args: >-
|
|
27
|
-
conda-build
|
|
28
|
-
boa
|
|
29
|
-
- run: conda mambabuild --channel conda-forge --channel scipp --no-anaconda-upload --override-channels --output-folder conda/package conda
|
|
30
|
-
|
|
31
|
-
- uses: actions/upload-artifact@v4
|
|
32
|
-
with:
|
|
33
|
-
name: conda-package-noarch
|
|
34
|
-
path: conda/package/noarch/*.tar.bz2
|
|
35
|
-
|
|
36
9
|
build_wheels:
|
|
37
10
|
name: Wheels
|
|
38
11
|
runs-on: 'ubuntu-24.04'
|
|
@@ -60,7 +33,7 @@ jobs:
|
|
|
60
33
|
|
|
61
34
|
upload_pypi:
|
|
62
35
|
name: Deploy PyPI
|
|
63
|
-
needs:
|
|
36
|
+
needs: build_wheels
|
|
64
37
|
runs-on: 'ubuntu-24.04'
|
|
65
38
|
environment: release
|
|
66
39
|
permissions:
|
|
@@ -70,25 +43,8 @@ jobs:
|
|
|
70
43
|
- uses: actions/download-artifact@v4
|
|
71
44
|
- uses: pypa/gh-action-pypi-publish@v1.12.4
|
|
72
45
|
|
|
73
|
-
upload_conda:
|
|
74
|
-
name: Deploy Conda
|
|
75
|
-
needs: [build_wheels, build_conda]
|
|
76
|
-
runs-on: 'ubuntu-24.04'
|
|
77
|
-
if: github.event_name == 'release' && github.event.action == 'published'
|
|
78
|
-
|
|
79
|
-
steps:
|
|
80
|
-
- uses: actions/download-artifact@v4
|
|
81
|
-
- uses: mamba-org/setup-micromamba@v1
|
|
82
|
-
with:
|
|
83
|
-
environment-name: upload-env
|
|
84
|
-
# frozen python due to breaking removal of 'imp' in 3.12
|
|
85
|
-
create-args: >-
|
|
86
|
-
anaconda-client
|
|
87
|
-
python=3.11
|
|
88
|
-
- run: anaconda --token ${{ secrets.ANACONDATOKEN }} upload --user scipp --label main $(ls conda-package-noarch/*.tar.bz2)
|
|
89
|
-
|
|
90
46
|
docs:
|
|
91
|
-
needs:
|
|
47
|
+
needs: upload_pypi
|
|
92
48
|
uses: ./.github/workflows/docs.yml
|
|
93
49
|
with:
|
|
94
50
|
publish: ${{ github.event_name == 'release' && github.event.action == 'published' }}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: plopp
|
|
3
|
-
Version: 25.
|
|
3
|
+
Version: 25.7.0
|
|
4
4
|
Summary: Visualization library for Scipp
|
|
5
5
|
Author: Scipp contributors
|
|
6
6
|
License: BSD 3-Clause License
|
|
@@ -84,7 +84,7 @@ Dynamic: license-file
|
|
|
84
84
|
|
|
85
85
|
[](CODE_OF_CONDUCT.md)
|
|
86
86
|
[](https://pypi.python.org/pypi/plopp)
|
|
87
|
-
[](https://anaconda.org/conda-forge/plopp)
|
|
88
88
|
[](https://scipp.github.io/plopp/)
|
|
89
89
|
[](LICENSE)
|
|
90
90
|
[](https://zenodo.org/badge/latestdoi/528859752)
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[](CODE_OF_CONDUCT.md)
|
|
4
4
|
[](https://pypi.python.org/pypi/plopp)
|
|
5
|
-
[](https://anaconda.org/conda-forge/plopp)
|
|
6
6
|
[](https://scipp.github.io/plopp/)
|
|
7
7
|
[](LICENSE)
|
|
8
8
|
[](https://zenodo.org/badge/latestdoi/528859752)
|
|
@@ -125,7 +125,7 @@
|
|
|
125
125
|
"metadata": {},
|
|
126
126
|
"outputs": [],
|
|
127
127
|
"source": [
|
|
128
|
-
"# Display figure
|
|
128
|
+
"# Display figure and play widget\n",
|
|
129
129
|
"ipw.VBox([fig, play])"
|
|
130
130
|
]
|
|
131
131
|
},
|
|
@@ -154,7 +154,12 @@
|
|
|
154
154
|
"execution_count": null,
|
|
155
155
|
"id": "10",
|
|
156
156
|
"metadata": {
|
|
157
|
-
"
|
|
157
|
+
"editable": true,
|
|
158
|
+
"nbsphinx": "hidden",
|
|
159
|
+
"slideshow": {
|
|
160
|
+
"slide_type": ""
|
|
161
|
+
},
|
|
162
|
+
"tags": []
|
|
158
163
|
},
|
|
159
164
|
"outputs": [],
|
|
160
165
|
"source": [
|
|
@@ -162,6 +167,147 @@
|
|
|
162
167
|
"# It is hidden from the online documentation.\n",
|
|
163
168
|
"fig.save('../_static/gallery/streaming-plot-thumbnail.png')"
|
|
164
169
|
]
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
"cell_type": "markdown",
|
|
173
|
+
"id": "11",
|
|
174
|
+
"metadata": {},
|
|
175
|
+
"source": [
|
|
176
|
+
"## Streaming on a 3D figure\n",
|
|
177
|
+
"\n",
|
|
178
|
+
"The same works for 3D scatter plots.\n",
|
|
179
|
+
"\n",
|
|
180
|
+
"We make a slightly different data generator:"
|
|
181
|
+
]
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
"cell_type": "code",
|
|
185
|
+
"execution_count": null,
|
|
186
|
+
"id": "12",
|
|
187
|
+
"metadata": {
|
|
188
|
+
"editable": true,
|
|
189
|
+
"slideshow": {
|
|
190
|
+
"slide_type": ""
|
|
191
|
+
},
|
|
192
|
+
"tags": []
|
|
193
|
+
},
|
|
194
|
+
"outputs": [],
|
|
195
|
+
"source": [
|
|
196
|
+
"class DataGen:\n",
|
|
197
|
+
" \"\"\"A data generator which makes new data on a cylindrical detector panel\"\"\"\n",
|
|
198
|
+
" def __init__(self):\n",
|
|
199
|
+
" nphi = 100\n",
|
|
200
|
+
" nz = 20\n",
|
|
201
|
+
"\n",
|
|
202
|
+
" r = sc.scalar(10.0, unit='m')\n",
|
|
203
|
+
" phi = sc.linspace('phi', 0, np.pi, nphi + 1, unit='rad')\n",
|
|
204
|
+
" z = sc.linspace('z', -3.0, 3.0, nz + 1, unit='m')\n",
|
|
205
|
+
"\n",
|
|
206
|
+
" p = sc.midpoints(phi)\n",
|
|
207
|
+
" x = r * sc.cos(p)\n",
|
|
208
|
+
" y = r * sc.sin(p)\n",
|
|
209
|
+
" sizes = {'z': nz, 'phi': nphi}\n",
|
|
210
|
+
"\n",
|
|
211
|
+
" self.data = sc.DataArray(\n",
|
|
212
|
+
" data=sc.zeros(sizes=sizes, unit='counts'),\n",
|
|
213
|
+
" coords={\n",
|
|
214
|
+
" 'z': z,\n",
|
|
215
|
+
" 'phi': phi,\n",
|
|
216
|
+
" 'position': sc.spatial.as_vectors(\n",
|
|
217
|
+
" sc.broadcast(x, sizes=sizes),\n",
|
|
218
|
+
" sc.broadcast(sc.midpoints(z), sizes=sizes),\n",
|
|
219
|
+
" sc.broadcast(y, sizes=sizes)\n",
|
|
220
|
+
" ),\n",
|
|
221
|
+
" },\n",
|
|
222
|
+
" )\n",
|
|
223
|
+
"\n",
|
|
224
|
+
" def __call__(self, iteration: int=0):\n",
|
|
225
|
+
" # Generate new data when called\n",
|
|
226
|
+
" npoints = 100\n",
|
|
227
|
+
" phi = sc.array(dims=['event'], values=np.random.normal(scale=0.5, loc=0.5*np.pi, size=npoints), unit='rad')\n",
|
|
228
|
+
" z = sc.array(dims=['event'], values=np.random.normal(scale=2, size=npoints), unit='m')\n",
|
|
229
|
+
" new_events = sc.DataArray(\n",
|
|
230
|
+
" data=sc.ones(sizes=phi.sizes, unit=\"counts\"),\n",
|
|
231
|
+
" coords={'phi': phi, 'z': z})\n",
|
|
232
|
+
" # Histogram and add to container\n",
|
|
233
|
+
" self.data += new_events.hist({x: self.data.coords[x] for x in (\"phi\", \"z\")})\n",
|
|
234
|
+
" return self.data\n",
|
|
235
|
+
"\n",
|
|
236
|
+
"data = DataGen()"
|
|
237
|
+
]
|
|
238
|
+
},
|
|
239
|
+
{
|
|
240
|
+
"cell_type": "markdown",
|
|
241
|
+
"id": "13",
|
|
242
|
+
"metadata": {},
|
|
243
|
+
"source": [
|
|
244
|
+
"We then connect the streaming node to a 3D scatter plot:"
|
|
245
|
+
]
|
|
246
|
+
},
|
|
247
|
+
{
|
|
248
|
+
"cell_type": "code",
|
|
249
|
+
"execution_count": null,
|
|
250
|
+
"id": "14",
|
|
251
|
+
"metadata": {
|
|
252
|
+
"editable": true,
|
|
253
|
+
"slideshow": {
|
|
254
|
+
"slide_type": ""
|
|
255
|
+
},
|
|
256
|
+
"tags": []
|
|
257
|
+
},
|
|
258
|
+
"outputs": [],
|
|
259
|
+
"source": [
|
|
260
|
+
"play = ipw.Play(min=0, max=500, interval=100)\n",
|
|
261
|
+
"play_node = pp.widget_node(play)\n",
|
|
262
|
+
"stream_node = pp.Node(data, iteration=play_node)\n",
|
|
263
|
+
"fig = pp.scatter3d(stream_node, pos='position', cbar=True, pixel_size=0.3, autoscale=False)"
|
|
264
|
+
]
|
|
265
|
+
},
|
|
266
|
+
{
|
|
267
|
+
"cell_type": "code",
|
|
268
|
+
"execution_count": null,
|
|
269
|
+
"id": "15",
|
|
270
|
+
"metadata": {
|
|
271
|
+
"editable": true,
|
|
272
|
+
"nbsphinx": "hidden",
|
|
273
|
+
"slideshow": {
|
|
274
|
+
"slide_type": ""
|
|
275
|
+
},
|
|
276
|
+
"tags": []
|
|
277
|
+
},
|
|
278
|
+
"outputs": [],
|
|
279
|
+
"source": [
|
|
280
|
+
"for _ in range(500):\n",
|
|
281
|
+
" play_node.notify_children(\"update\")\n",
|
|
282
|
+
"fig.view.fit_to_data()"
|
|
283
|
+
]
|
|
284
|
+
},
|
|
285
|
+
{
|
|
286
|
+
"cell_type": "code",
|
|
287
|
+
"execution_count": null,
|
|
288
|
+
"id": "16",
|
|
289
|
+
"metadata": {
|
|
290
|
+
"editable": true,
|
|
291
|
+
"slideshow": {
|
|
292
|
+
"slide_type": ""
|
|
293
|
+
},
|
|
294
|
+
"tags": []
|
|
295
|
+
},
|
|
296
|
+
"outputs": [],
|
|
297
|
+
"source": [
|
|
298
|
+
"# Display figure and play widget\n",
|
|
299
|
+
"ipw.VBox([fig, play])"
|
|
300
|
+
]
|
|
301
|
+
},
|
|
302
|
+
{
|
|
303
|
+
"cell_type": "code",
|
|
304
|
+
"execution_count": null,
|
|
305
|
+
"id": "17",
|
|
306
|
+
"metadata": {},
|
|
307
|
+
"outputs": [],
|
|
308
|
+
"source": [
|
|
309
|
+
"pp.show_graph(fig)"
|
|
310
|
+
]
|
|
165
311
|
}
|
|
166
312
|
],
|
|
167
313
|
"metadata": {
|
|
@@ -61,6 +61,48 @@
|
|
|
61
61
|
"source": [
|
|
62
62
|
"pp.slicer(da, keep=['x'])"
|
|
63
63
|
]
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
"cell_type": "markdown",
|
|
67
|
+
"id": "6",
|
|
68
|
+
"metadata": {},
|
|
69
|
+
"source": [
|
|
70
|
+
"## Animate the sliders\n",
|
|
71
|
+
"\n",
|
|
72
|
+
"<div class=\"versionadded\" style=\"font-weight: bold;\">\n",
|
|
73
|
+
"\n",
|
|
74
|
+
"<img src=\"../_static/circle-exclamation.svg\" width=\"16\" height=\"16\" />\n",
|
|
75
|
+
" \n",
|
|
76
|
+
"New in version 25.07.0.\n",
|
|
77
|
+
"\n",
|
|
78
|
+
"</div>\n",
|
|
79
|
+
"\n",
|
|
80
|
+
"It is possible to display some animation controls (play button) next to the slider,\n",
|
|
81
|
+
"by using the `enable_player=True` option:"
|
|
82
|
+
]
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
"cell_type": "code",
|
|
86
|
+
"execution_count": null,
|
|
87
|
+
"id": "7",
|
|
88
|
+
"metadata": {},
|
|
89
|
+
"outputs": [],
|
|
90
|
+
"source": [
|
|
91
|
+
"pp.slicer(da, keep=['x', 'y'], enable_player=True)"
|
|
92
|
+
]
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
"cell_type": "markdown",
|
|
96
|
+
"id": "8",
|
|
97
|
+
"metadata": {},
|
|
98
|
+
"source": [
|
|
99
|
+
"## Can I have a 3D plot with a slider?\n",
|
|
100
|
+
"\n",
|
|
101
|
+
"3D plots are not supported out of the box by the [plopp.slicer](../generated/plopp.slicer.rst) function,\n",
|
|
102
|
+
"but it is still possible to create them.\n",
|
|
103
|
+
"\n",
|
|
104
|
+
"An example in the [gallery](../gallery/scatter3d-with-slider.ipynb) shows you how to do this."
|
|
105
|
+
]
|
|
64
106
|
}
|
|
65
107
|
],
|
|
66
108
|
"metadata": {
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
"source": [
|
|
58
58
|
"tool = p.right_bar[0]\n",
|
|
59
59
|
"b = tool.button\n",
|
|
60
|
-
"sl = p.bottom_bar[0].controls['y']
|
|
60
|
+
"sl = p.bottom_bar[0].controls['y']\n",
|
|
61
61
|
"b.click()\n",
|
|
62
62
|
"sl.value = 20\n",
|
|
63
63
|
"b.click()\n",
|
|
@@ -102,8 +102,7 @@
|
|
|
102
102
|
"mimetype": "text/x-python",
|
|
103
103
|
"name": "python",
|
|
104
104
|
"nbconvert_exporter": "python",
|
|
105
|
-
"pygments_lexer": "ipython3"
|
|
106
|
-
"version": "3.11.9"
|
|
105
|
+
"pygments_lexer": "ipython3"
|
|
107
106
|
}
|
|
108
107
|
},
|
|
109
108
|
"nbformat": 4,
|
|
@@ -23,8 +23,8 @@ def _make_graphviz_digraph(*args, **kwargs):
|
|
|
23
23
|
def _walk_graph(start, nodes, edges, views, labels):
|
|
24
24
|
label = (
|
|
25
25
|
escape(str(start.func)) + '\nid = ' + start.id
|
|
26
|
-
if start.
|
|
27
|
-
else escape(start.
|
|
26
|
+
if start.pretty_name is None
|
|
27
|
+
else escape(start.pretty_name)
|
|
28
28
|
)
|
|
29
29
|
nodes[start.id] = label
|
|
30
30
|
for child in start.children:
|
|
@@ -38,6 +38,6 @@ def widget_node(widget) -> Node:
|
|
|
38
38
|
``ipywidgets`` library, or a custom widget.
|
|
39
39
|
"""
|
|
40
40
|
n = Node(func=lambda: widget.value)
|
|
41
|
-
n.
|
|
41
|
+
n.pretty_name = f'Widget <{type(widget).__name__}: {type(widget.value).__name__}>'
|
|
42
42
|
widget.observe(n.notify_children, names="value")
|
|
43
43
|
return n
|
|
@@ -64,10 +64,10 @@ class Node:
|
|
|
64
64
|
)
|
|
65
65
|
)
|
|
66
66
|
fname = getattr(self.func, "__name__", str(self.func))
|
|
67
|
-
self.
|
|
67
|
+
self.pretty_name = f'{fname}({args_string})'
|
|
68
68
|
else:
|
|
69
69
|
val_str = f'={func!r}' if isinstance(func, int | float | str) else ""
|
|
70
|
-
self.
|
|
70
|
+
self.pretty_name = f'Input <{type(func).__name__}{val_str}>'
|
|
71
71
|
|
|
72
72
|
# Attempt to set children after setting name in case error message is needed
|
|
73
73
|
for parent in chain(self.parents, self.kwparents.values()):
|
|
@@ -194,7 +194,7 @@ class Node:
|
|
|
194
194
|
return self.id == other.id
|
|
195
195
|
|
|
196
196
|
def __repr__(self) -> str:
|
|
197
|
-
return f"Node(name={self.
|
|
197
|
+
return f"Node(name={self.pretty_name})"
|
|
198
198
|
|
|
199
199
|
def __add__(self, other: Node | Any) -> Node:
|
|
200
200
|
return Node(lambda x, y: x + y, self, other)
|
|
@@ -59,7 +59,7 @@ class GraphicalView(View):
|
|
|
59
59
|
title: str | None = None,
|
|
60
60
|
figsize: tuple[float, float] | None = None,
|
|
61
61
|
format: Literal['svg', 'png'] | None = None,
|
|
62
|
-
legend: bool | tuple[float, float] =
|
|
62
|
+
legend: bool | tuple[float, float] = True,
|
|
63
63
|
camera: Camera | None = None,
|
|
64
64
|
autoscale: bool = True,
|
|
65
65
|
ax: Any = None,
|
|
@@ -76,64 +76,28 @@ def to_variable(obj) -> sc.Variable:
|
|
|
76
76
|
return out
|
|
77
77
|
|
|
78
78
|
|
|
79
|
-
def
|
|
80
|
-
da: sc.DataArray, coords: list[str] | None
|
|
81
|
-
) -> sc.DataArray:
|
|
82
|
-
if coords is None:
|
|
83
|
-
coords = list(da.dims)
|
|
84
|
-
elif missing := set(coords) - set(da.coords.keys()):
|
|
85
|
-
raise ValueError(f"Specified coords do not exist: {missing}")
|
|
86
|
-
|
|
87
|
-
# Remove unused coords
|
|
88
|
-
da = da.drop_coords(list(set(da.coords) - set(coords)))
|
|
89
|
-
# Assign dim coords where missing. The above checks ensure that all missing
|
|
90
|
-
# coords are dim coords, i.e., that `name in out.dims`.
|
|
91
|
-
da = da.assign_coords(
|
|
92
|
-
{
|
|
93
|
-
name: sc.arange(name, da.sizes[name], unit=None)
|
|
94
|
-
for name in set(coords) - set(da.coords)
|
|
95
|
-
}
|
|
96
|
-
)
|
|
97
|
-
return da
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
def to_data_array(
|
|
101
|
-
obj: Plottable | list,
|
|
102
|
-
coords: list[str] | None = None,
|
|
103
|
-
) -> sc.DataArray:
|
|
79
|
+
def to_data_array(obj: Plottable | list) -> sc.DataArray:
|
|
104
80
|
"""
|
|
105
|
-
Convert an input to a DataArray
|
|
106
|
-
|
|
81
|
+
Convert an input to a DataArray.
|
|
82
|
+
Returns a shallow copy of the input if it is already a DataArray.
|
|
107
83
|
|
|
108
84
|
Parameters
|
|
109
85
|
----------
|
|
110
86
|
obj:
|
|
111
87
|
The input object to be converted.
|
|
112
|
-
coords:
|
|
113
|
-
If supplied, use these coords instead of the input's dimension coordinates.
|
|
114
88
|
"""
|
|
89
|
+
if isinstance(obj, sc.DataArray):
|
|
90
|
+
return obj.copy(deep=False)
|
|
115
91
|
out = _maybe_to_variable(obj)
|
|
116
92
|
if isinstance(out, sc.Variable):
|
|
117
93
|
out = sc.DataArray(data=out)
|
|
118
94
|
out = from_compatible_lib(out)
|
|
119
95
|
if not isinstance(out, sc.DataArray):
|
|
120
96
|
raise TypeError(f"Cannot convert input of type {type(obj)} to a DataArray.")
|
|
121
|
-
out = _ensure_data_array_coords(out, coords)
|
|
122
|
-
for name, coord in out.coords.items():
|
|
123
|
-
if not coord.dims:
|
|
124
|
-
raise ValueError(
|
|
125
|
-
"Input data cannot be plotted: it has a scalar coordinate along "
|
|
126
|
-
f"dimension {name}. Consider dropping this coordinate before plotting. "
|
|
127
|
-
f"Use ``data.drop_coords('{name}').plot()``."
|
|
128
|
-
)
|
|
129
|
-
for name in out.coords:
|
|
130
|
-
other_dims = [dim for dim in out.coords[name].dims if dim not in out.dims]
|
|
131
|
-
for dim in other_dims:
|
|
132
|
-
out.coords[name] = out.coords[name].mean(dim)
|
|
133
97
|
return out
|
|
134
98
|
|
|
135
99
|
|
|
136
|
-
def _check_size(da: sc.DataArray):
|
|
100
|
+
def _check_size(da: sc.DataArray) -> None:
|
|
137
101
|
"""
|
|
138
102
|
Prevent slow figure rendering by raising an error if the data array exceeds a
|
|
139
103
|
default size.
|
|
@@ -149,7 +113,7 @@ def _check_size(da: sc.DataArray):
|
|
|
149
113
|
)
|
|
150
114
|
|
|
151
115
|
|
|
152
|
-
def check_not_binned(da: sc.DataArray):
|
|
116
|
+
def check_not_binned(da: sc.DataArray) -> None:
|
|
153
117
|
"""
|
|
154
118
|
Plopp cannot plot binned data.
|
|
155
119
|
This function will raise an error if the input data is binned.
|
|
@@ -169,7 +133,7 @@ def check_not_binned(da: sc.DataArray):
|
|
|
169
133
|
)
|
|
170
134
|
|
|
171
135
|
|
|
172
|
-
def check_allowed_dtypes(da: sc.DataArray):
|
|
136
|
+
def check_allowed_dtypes(da: sc.DataArray) -> None:
|
|
173
137
|
"""
|
|
174
138
|
Currently, Plopp cannot plot data that contains vector and matrix dtypes.
|
|
175
139
|
This function will raise an error if the input data type is not supported.
|
|
@@ -185,10 +149,108 @@ def check_allowed_dtypes(da: sc.DataArray):
|
|
|
185
149
|
)
|
|
186
150
|
|
|
187
151
|
|
|
188
|
-
def _all_dims_sorted(var, order='ascending'):
|
|
152
|
+
def _all_dims_sorted(var, order='ascending') -> bool:
|
|
153
|
+
"""
|
|
154
|
+
Check if all dimensions of a variable are sorted in the specified order.
|
|
155
|
+
This is used to ensure that the coordinates are sorted before plotting.
|
|
156
|
+
"""
|
|
189
157
|
return all(sc.allsorted(var, dim, order=order) for dim in var.dims)
|
|
190
158
|
|
|
191
159
|
|
|
160
|
+
def _rename_dims_from_coords(da: sc.DataArray, coords: Iterable[str]) -> sc.DataArray:
|
|
161
|
+
"""
|
|
162
|
+
If coordinates are provided, rename the dimensions of the data array to match the
|
|
163
|
+
names of the coordinates, so that they effectively become the dimension coordinates.
|
|
164
|
+
"""
|
|
165
|
+
renamed_dims = {}
|
|
166
|
+
underlying_dims = set()
|
|
167
|
+
for dim in coords:
|
|
168
|
+
underlying = da.coords[dim].dims[-1]
|
|
169
|
+
if underlying in underlying_dims:
|
|
170
|
+
raise ValueError(
|
|
171
|
+
"coords: Cannot use more than one coordinate associated with "
|
|
172
|
+
f"the same underlying dimension ({underlying})."
|
|
173
|
+
)
|
|
174
|
+
renamed_dims[underlying] = dim
|
|
175
|
+
underlying_dims.add(underlying)
|
|
176
|
+
return da.rename_dims(**renamed_dims)
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
def _add_missing_dimension_coords(da: sc.DataArray) -> sc.DataArray:
|
|
180
|
+
"""
|
|
181
|
+
Add missing dimension coordinates to the data array.
|
|
182
|
+
If a dimension does not have a coordinate, it will be added with a range of values.
|
|
183
|
+
"""
|
|
184
|
+
return da.assign_coords(
|
|
185
|
+
{
|
|
186
|
+
dim: sc.arange(dim, da.sizes[dim], unit=None)
|
|
187
|
+
for dim in da.dims
|
|
188
|
+
if dim not in da.coords
|
|
189
|
+
}
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
def _drop_non_dimension_coords(da: sc.DataArray) -> sc.DataArray:
|
|
194
|
+
"""
|
|
195
|
+
Drop all coordinates that are not dimension coordinates.
|
|
196
|
+
This is useful to ensure that only the coordinates that are actually used for
|
|
197
|
+
plotting are kept.
|
|
198
|
+
"""
|
|
199
|
+
return da.drop_coords([name for name in da.coords if name not in da.dims])
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
def _handle_coords_with_left_over_dimensions(da: sc.DataArray) -> sc.DataArray:
|
|
203
|
+
"""
|
|
204
|
+
In some rare cases, the coordinate may have dimensions that are not present in the
|
|
205
|
+
data array. This can happen for example when a 2d coord with bin edges is sliced
|
|
206
|
+
along one dimension, leaving a coordinate with the other dimension, and a dimension
|
|
207
|
+
of length 2 (because of the bin edges) in th sliced dimension.
|
|
208
|
+
|
|
209
|
+
This function will handle such cases by averaging the coordinate over the left-over
|
|
210
|
+
dimensions, effectively reducing the coordinate to a single value for each
|
|
211
|
+
dimension that is not present in the data array.
|
|
212
|
+
"""
|
|
213
|
+
return da.assign_coords(
|
|
214
|
+
{
|
|
215
|
+
name: da.coords[name].mean(
|
|
216
|
+
[dim for dim in da.coords[name].dims if dim not in da.dims]
|
|
217
|
+
)
|
|
218
|
+
for name in da.coords
|
|
219
|
+
}
|
|
220
|
+
)
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
def _check_coord_sanity(da: sc.DataArray) -> None:
|
|
224
|
+
"""
|
|
225
|
+
Warn if any coordinate is not sorted. This can lead to unpredictable results
|
|
226
|
+
when plotting.
|
|
227
|
+
Also, raise an error if any coordinate is scalar.
|
|
228
|
+
"""
|
|
229
|
+
for name, coord in da.coords.items():
|
|
230
|
+
try:
|
|
231
|
+
if not (
|
|
232
|
+
_all_dims_sorted(coord, order='ascending')
|
|
233
|
+
or _all_dims_sorted(coord, order='descending')
|
|
234
|
+
):
|
|
235
|
+
warnings.warn(
|
|
236
|
+
'The input contains a coordinate with unsorted values '
|
|
237
|
+
f'({name}). The results may be unpredictable. '
|
|
238
|
+
'Coordinates can be sorted using '
|
|
239
|
+
'`scipp.sort(data, dim="to_be_sorted", order="ascending")`.',
|
|
240
|
+
RuntimeWarning,
|
|
241
|
+
stacklevel=2,
|
|
242
|
+
)
|
|
243
|
+
except sc.DTypeError:
|
|
244
|
+
pass
|
|
245
|
+
|
|
246
|
+
if not coord.dims:
|
|
247
|
+
raise ValueError(
|
|
248
|
+
"Input data cannot be plotted: it has a scalar coordinate along "
|
|
249
|
+
f"dimension {name}. Consider dropping this coordinate before plotting. "
|
|
250
|
+
f"Use ``data.drop_coords('{name}').plot()``."
|
|
251
|
+
)
|
|
252
|
+
|
|
253
|
+
|
|
192
254
|
def preprocess(
|
|
193
255
|
obj: Plottable | list,
|
|
194
256
|
name: str | None = None,
|
|
@@ -219,42 +281,19 @@ def preprocess(
|
|
|
219
281
|
elif coords is not None:
|
|
220
282
|
coords = list(coords)
|
|
221
283
|
|
|
222
|
-
out = to_data_array(obj
|
|
284
|
+
out = to_data_array(obj)
|
|
223
285
|
check_not_binned(out)
|
|
224
286
|
check_allowed_dtypes(out)
|
|
225
287
|
if name is not None:
|
|
226
|
-
out.name = name
|
|
288
|
+
out.name = str(name)
|
|
227
289
|
if not ignore_size:
|
|
228
290
|
_check_size(out)
|
|
229
291
|
if coords is not None:
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
"coords: Cannot use more than one coordinate associated with "
|
|
236
|
-
f"the same underlying dimension ({underlying})."
|
|
237
|
-
)
|
|
238
|
-
renamed_dims[underlying] = dim
|
|
239
|
-
out = out.rename_dims(**renamed_dims)
|
|
240
|
-
for n, coord in out.coords.items():
|
|
241
|
-
if (coord.ndim == 0) or (n not in out.dims):
|
|
242
|
-
continue
|
|
243
|
-
try:
|
|
244
|
-
if not (
|
|
245
|
-
_all_dims_sorted(coord, order='ascending')
|
|
246
|
-
or _all_dims_sorted(coord, order='descending')
|
|
247
|
-
):
|
|
248
|
-
warnings.warn(
|
|
249
|
-
'The input contains a coordinate with unsorted values '
|
|
250
|
-
f'({n}). The results may be unpredictable. '
|
|
251
|
-
'Coordinates can be sorted using '
|
|
252
|
-
'`scipp.sort(data, dim="to_be_sorted", order="ascending")`.',
|
|
253
|
-
RuntimeWarning,
|
|
254
|
-
stacklevel=2,
|
|
255
|
-
)
|
|
256
|
-
except sc.DTypeError:
|
|
257
|
-
pass
|
|
292
|
+
out = _rename_dims_from_coords(out, coords)
|
|
293
|
+
out = _add_missing_dimension_coords(out)
|
|
294
|
+
out = _drop_non_dimension_coords(out)
|
|
295
|
+
out = _handle_coords_with_left_over_dimensions(out)
|
|
296
|
+
_check_coord_sanity(out)
|
|
258
297
|
return out
|
|
259
298
|
|
|
260
299
|
|
|
@@ -277,9 +316,9 @@ def input_to_nodes(obj: PlottableMulti, processor: Callable) -> list[Node]:
|
|
|
277
316
|
nodes = [Node(processor, inp, name=name) for name, inp in to_nodes]
|
|
278
317
|
for node in nodes:
|
|
279
318
|
if hasattr(processor, 'func'):
|
|
280
|
-
node.
|
|
319
|
+
node.pretty_name = processor.func.__name__
|
|
281
320
|
else:
|
|
282
|
-
node.
|
|
321
|
+
node.pretty_name = 'Preprocess data'
|
|
283
322
|
return nodes
|
|
284
323
|
|
|
285
324
|
|