├── .github └── workflows │ └── regression-tests.yml ├── .gitignore ├── .readthedocs.yaml ├── LICENSE ├── README.md ├── artwork ├── toyplot-256x256.png ├── toyplot.lxo └── toyplot.png ├── behave.ini ├── docs ├── .gitignore ├── Makefile ├── arrow.inv ├── canvas-layout.ipynb ├── cartesian-coordinates.ipynb ├── case-studies.rst ├── color-mapping.ipynb ├── colors.ipynb ├── communities-case-study.ipynb ├── compatibility.rst ├── conf.py ├── convenience-api.ipynb ├── credits.rst ├── css │ ├── SNL_Stacked_Black.png │ ├── toyplot-rtd.css │ └── toyplot.css ├── data-tables.ipynb ├── development.rst ├── docs.py ├── documentation-embedding.png ├── ellipse-visualization.ipynb ├── embedding.rst ├── ethos.rst ├── graph-visualization.ipynb ├── image-visualization.ipynb ├── index.rst ├── installation.rst ├── interaction.ipynb ├── javascript.rst ├── jet.npy ├── js │ ├── toyplot.canvas.id.rst │ ├── toyplot.canvas.rst │ ├── toyplot.io.rst │ ├── toyplot.menus.context.rst │ ├── toyplot.root.id.rst │ ├── toyplot.root.rst │ └── toyplot.tables.rst ├── jupyter-embedding.png ├── labels-and-legends.ipynb ├── log-scales.ipynb ├── make.bat ├── markers.ipynb ├── matrix-visualization.ipynb ├── neural-network-case-study.ipynb ├── null-data.ipynb ├── numberline-coordinates.ipynb ├── numpy.inv ├── pandas.inv ├── pillow.inv ├── projects.rst ├── python.inv ├── qtconsole-embedding.png ├── reference.rst ├── release-notes.rst ├── rendering.ipynb ├── requirements.txt ├── support.rst ├── table-coordinates.ipynb ├── text.ipynb ├── tick-locators.ipynb ├── toyplot.bitmap.rst ├── toyplot.broadcast.rst ├── toyplot.browser.rst ├── toyplot.canvas.rst ├── toyplot.color.rst ├── toyplot.config.rst ├── toyplot.coordinates.rst ├── toyplot.data.rst ├── toyplot.font.rst ├── toyplot.format.rst ├── toyplot.hou.rst ├── toyplot.html.rst ├── toyplot.layout.rst ├── toyplot.locator.rst ├── toyplot.mark.rst ├── toyplot.marker.rst ├── toyplot.pdf.rst ├── toyplot.png.rst ├── toyplot.projection.rst ├── toyplot.reportlab.pdf.rst ├── toyplot.reportlab.png.rst ├── toyplot.reportlab.rst ├── toyplot.require.rst ├── toyplot.rst ├── toyplot.scenegraph.rst ├── toyplot.style.rst ├── toyplot.svg.rst ├── toyplot.text.rst ├── toyplot.transform.rst ├── toyplot.units.rst ├── tutorial.ipynb ├── units.ipynb ├── user-guide.rst └── violin-plots-case-study.ipynb ├── features ├── administrivia.feature ├── backend.feature ├── bar-visualization.feature ├── browser.feature ├── canvas.feature ├── cartesian-coordinates.feature ├── color-broadcasting.feature ├── color-conversion.feature ├── color-palette.feature ├── color-scale.feature ├── colormap.feature ├── data-table.feature ├── data.feature ├── documentation.feature ├── ellipse-visualization.feature ├── fill-visualization.feature ├── format.feature ├── graph-visualization.feature ├── image-visualization.feature ├── legends.feature ├── line-visualization.feature ├── log-scale-axes.feature ├── matrix-visualization.feature ├── opacity-broadcasting.feature ├── plot-visualization.feature ├── projection.feature ├── rectangle-visualization.feature ├── reference │ ├── axes-cartesian-defaults.svg │ ├── axes-cartesian-empty-shared-x-axis.svg │ ├── axes-cartesian-label.svg │ ├── axes-cartesian-shared-x-axis.svg │ ├── axes-cartesian-show.svg │ ├── axes-cartesian-x-domain.svg │ ├── axes-cartesian-x-label.svg │ ├── axes-cartesian-x-scale.svg │ ├── axes-cartesian-x-show.svg │ ├── axes-cartesian-x-spine-position-high.svg │ ├── axes-cartesian-x-spine-position.svg │ ├── axes-cartesian-x-spine-show.svg │ ├── axes-cartesian-x-spine-style.svg │ ├── axes-cartesian-x-ticks-labels-angle.svg │ ├── axes-cartesian-x-ticks-labels-label-index-style.svg │ ├── axes-cartesian-x-ticks-labels-label-value-style.svg │ ├── axes-cartesian-x-ticks-labels-offset.svg │ ├── axes-cartesian-x-ticks-labels-show.svg │ ├── axes-cartesian-x-ticks-labels-style.svg │ ├── axes-cartesian-x-ticks-locator.svg │ ├── axes-cartesian-x-ticks-show.svg │ ├── axes-cartesian-x-ticks-sized.svg │ ├── axes-cartesian-x-ticks-style.svg │ ├── axes-cartesian-x-ticks-tick-index-style.svg │ ├── axes-cartesian-x-ticks-tick-value-style.svg │ ├── axes-cartesian-y-domain.svg │ ├── axes-cartesian-y-label.svg │ ├── axes-cartesian-y-scale.svg │ ├── axes-cartesian-y-show.svg │ ├── axes-cartesian-y-spine-position-high.svg │ ├── axes-cartesian-y-spine-position.svg │ ├── axes-cartesian-y-spine-show.svg │ ├── axes-cartesian-y-spine-style.svg │ ├── axes-cartesian-y-ticks-labels-angle.svg │ ├── axes-cartesian-y-ticks-labels-label-index-style.svg │ ├── axes-cartesian-y-ticks-labels-label-value-style.svg │ ├── axes-cartesian-y-ticks-labels-offset.svg │ ├── axes-cartesian-y-ticks-labels-show.svg │ ├── axes-cartesian-y-ticks-labels-style.svg │ ├── axes-cartesian-y-ticks-locator.svg │ ├── axes-cartesian-y-ticks-show.svg │ ├── axes-cartesian-y-ticks-sized.svg │ ├── axes-cartesian-y-ticks-style.svg │ ├── axes-cartesian-y-ticks-tick-index-style.svg │ ├── axes-cartesian-y-ticks-tick-value-style.svg │ ├── axes-fill-boundaries-masked-nan.svg │ ├── axes-fill-magnitudes-masked-nan.svg │ ├── axes-fill-n-boundaries-position-along-y.svg │ ├── axes-fill-n-boundaries-position.svg │ ├── axes-fill-n-boundaries-titles.svg │ ├── axes-fill-n-boundaries.svg │ ├── axes-fill-n-magnitudes-position-along-y.svg │ ├── axes-fill-n-magnitudes-position-titles.svg │ ├── axes-fill-n-magnitudes-position.svg │ ├── axes-fill-n-magnitudes-symmetric-baseline.svg │ ├── axes-fill-n-magnitudes-wiggle-baseline.svg │ ├── axes-fill-n-magnitudes.svg │ ├── axes-fill-one-boundary-position.svg │ ├── axes-fill-one-boundary.svg │ ├── axes-fill-one-magnitude-position.svg │ ├── axes-fill-one-magnitude.svg │ ├── axes-fill-two-boundaries-position.svg │ ├── axes-lines-annotation.svg │ ├── axes-lines-data.svg │ ├── axes-log-10-scale-0-100-domain-min-10.svg │ ├── axes-log-10-scale-negative-100-0-domain-max-negative-10.svg │ ├── axes-log-10-scale-negative-1000-1000-custom-format.svg │ ├── axes-log-2-scale-1-1000.svg │ ├── axes-log-2-scale-negative-1000-1000.svg │ ├── axes-log-2-scale-negative-1000-negative-1.svg │ ├── axes-log-scale-0.01-1000.svg │ ├── axes-log-scale-1-1000.svg │ ├── axes-log-scale-negative-0.5-1000.svg │ ├── axes-log-scale-negative-1000-0.5.svg │ ├── axes-log-scale-negative-1000-1000.svg │ ├── axes-log-scale-negative-1000-negative-0.01.svg │ ├── axes-log-scale-negative-1000-negative-1.svg │ ├── axes-log-scale-negative-1000-zero.svg │ ├── axes-log-scale-zero-1000.svg │ ├── axes-palette.svg │ ├── axes-palettes.svg │ ├── axes-plot-masked-nan.svg │ ├── axes-plot-n-variables-along-y.svg │ ├── axes-plot-n-variables-x.svg │ ├── axes-plot-n-variables.svg │ ├── axes-plot-one-variable-x.svg │ ├── axes-plot-one-variable.svg │ ├── axes-rect-singular-along-y.svg │ ├── axes-rect-singular.svg │ ├── axes-rect.svg │ ├── axes-scatterplot-markers.svg │ ├── axes-scatterplot-n-variables-along-y.svg │ ├── axes-scatterplot-n-variables-x.svg │ ├── axes-scatterplot-n-variables.svg │ ├── axes-scatterplot-one-variable-fill.svg │ ├── axes-scatterplot-one-variable-x.svg │ ├── axes-scatterplot-one-variable.svg │ ├── axes-scatterplot-singular.svg │ ├── axes-tick-titles.svg │ ├── bars-boundaries-masked-nan.svg │ ├── bars-histogram.svg │ ├── bars-magnitudes-masked-nan.svg │ ├── bars-n-boundaries-along-y.svg │ ├── bars-n-boundaries-centers.svg │ ├── bars-n-boundaries-edges.svg │ ├── bars-n-boundaries-titles.svg │ ├── bars-n-boundaries.svg │ ├── bars-n-magnitudes-along-y.svg │ ├── bars-n-magnitudes-centers.svg │ ├── bars-n-magnitudes-edges.svg │ ├── bars-n-magnitudes-symmetric.svg │ ├── bars-n-magnitudes-titles.svg │ ├── bars-n-magnitudes-wiggle.svg │ ├── bars-n-magnitudes.svg │ ├── bars-one-boundary-centers.svg │ ├── bars-one-boundary-edges.svg │ ├── bars-one-boundary.svg │ ├── bars-one-magnitude-centers.svg │ ├── bars-one-magnitude-edges.svg │ ├── bars-one-magnitude.svg │ ├── canvas-layout-bounds.svg │ ├── canvas-layout-corner.svg │ ├── canvas-layout-default.svg │ ├── canvas-layout-grid.svg │ ├── canvas-layout-numberline-relative.svg │ ├── canvas-layout-rect.svg │ ├── color-brewer-Accent.html │ ├── color-brewer-BlueGreen.html │ ├── color-brewer-BlueGreenBrown.html │ ├── color-brewer-BlueGreenYellow.html │ ├── color-brewer-BluePurple.html │ ├── color-brewer-BlueRed.html │ ├── color-brewer-BlueYellowRed.html │ ├── color-brewer-Blues.html │ ├── color-brewer-BrownOrangeYellow.html │ ├── color-brewer-Dark2.html │ ├── color-brewer-GrayRed.html │ ├── color-brewer-GreenBlue.html │ ├── color-brewer-GreenBluePurple.html │ ├── color-brewer-GreenYellow.html │ ├── color-brewer-GreenYellowRed.html │ ├── color-brewer-Greens.html │ ├── color-brewer-Greys.html │ ├── color-brewer-Oranges.html │ ├── color-brewer-Paired.html │ ├── color-brewer-Pastel1.html │ ├── color-brewer-Pastel2.html │ ├── color-brewer-PinkGreen.html │ ├── color-brewer-PurpleBlue.html │ ├── color-brewer-PurpleGreen.html │ ├── color-brewer-PurpleOrange.html │ ├── color-brewer-PurpleRed.html │ ├── color-brewer-Purples.html │ ├── color-brewer-RedOrange.html │ ├── color-brewer-RedOrangeYellow.html │ ├── color-brewer-RedPurple.html │ ├── color-brewer-Reds.html │ ├── color-brewer-Set1.html │ ├── color-brewer-Set2.html │ ├── color-brewer-Set3.html │ ├── color-brewer-Spectral.html │ ├── color-brewer-count.html │ ├── color-brewer-reverse.html │ ├── color-brewer.html │ ├── color-broadcast-bars-colormap.svg │ ├── color-broadcast-bars-default.svg │ ├── color-broadcast-bars-one-color.svg │ ├── color-broadcast-bars-per-datum-colors.svg │ ├── color-broadcast-bars-per-datum-values-colormap.svg │ ├── color-broadcast-bars-per-datum-values.svg │ ├── color-broadcast-bars-per-series-colors.svg │ ├── color-broadcast-bars-per-series-values-colormap.svg │ ├── color-broadcast-bars-per-series-values.svg │ ├── color-broadcast-css-array.svg │ ├── color-broadcast-fills-colormap.svg │ ├── color-broadcast-fills-default.svg │ ├── color-broadcast-fills-one-color.svg │ ├── color-broadcast-fills-per-series-colors.svg │ ├── color-broadcast-fills-per-series-values-colormap.svg │ ├── color-broadcast-fills-per-series-values.svg │ ├── color-broadcast-hlines-colormap.svg │ ├── color-broadcast-hlines-default.svg │ ├── color-broadcast-hlines-one-color.svg │ ├── color-broadcast-hlines-per-datum-colors.svg │ ├── color-broadcast-hlines-per-datum-values-colormap.svg │ ├── color-broadcast-hlines-per-datum-values.svg │ ├── color-broadcast-plots-colormap-marker.svg │ ├── color-broadcast-plots-colormap.svg │ ├── color-broadcast-plots-default.svg │ ├── color-broadcast-plots-marker-default.svg │ ├── color-broadcast-plots-one-color.svg │ ├── color-broadcast-plots-one-marker-color.svg │ ├── color-broadcast-plots-per-datum-values-colormap-marker.svg │ ├── color-broadcast-plots-per-datum-values-marker.svg │ ├── color-broadcast-plots-per-series-colors.svg │ ├── color-broadcast-plots-per-series-marker-colors.svg │ ├── color-broadcast-plots-per-series-values-colormap-marker.svg │ ├── color-broadcast-plots-per-series-values-colormap.svg │ ├── color-broadcast-plots-per-series-values-marker.svg │ ├── color-broadcast-plots-per-series-values.svg │ ├── color-broadcast-rects-colormap.svg │ ├── color-broadcast-rects-default.svg │ ├── color-broadcast-rects-one-color.svg │ ├── color-broadcast-rects-per-datum-colors.svg │ ├── color-broadcast-rects-per-datum-values-colormap.svg │ ├── color-broadcast-rects-per-datum-values.svg │ ├── color-broadcast-scatterplots-colormap.svg │ ├── color-broadcast-scatterplots-default.svg │ ├── color-broadcast-scatterplots-one-color.svg │ ├── color-broadcast-scatterplots-per-datum-colors.svg │ ├── color-broadcast-scatterplots-per-datum-values-colormap.svg │ ├── color-broadcast-scatterplots-per-datum-values.svg │ ├── color-broadcast-scatterplots-per-series-colors.svg │ ├── color-broadcast-scatterplots-per-series-values-colormap.svg │ ├── color-broadcast-scatterplots-per-series-values.svg │ ├── color-broadcast-text-colormap.svg │ ├── color-broadcast-text-default.svg │ ├── color-broadcast-text-one-color.svg │ ├── color-broadcast-text-per-datum-colors.svg │ ├── color-broadcast-text-per-datum-values-colormap.svg │ ├── color-broadcast-text-per-datum-values.svg │ ├── color-broadcast-vlines-colormap.svg │ ├── color-broadcast-vlines-default.svg │ ├── color-broadcast-vlines-one-color.svg │ ├── color-broadcast-vlines-per-datum-colors.svg │ ├── color-broadcast-vlines-per-datum-values-colormap.svg │ ├── color-broadcast-vlines-per-datum-values.svg │ ├── color-categorical-map.html │ ├── color-diverging-map-BlueBrown.html │ ├── color-diverging-map-BlueRed.html │ ├── color-diverging-map-GreenRed.html │ ├── color-diverging-map-PurpleGreen.html │ ├── color-diverging-map-PurpleOrange.html │ ├── color-diverging-map-custom.html │ ├── color-diverging-map.html │ ├── color-linear-map.html │ ├── color-palette-add.html │ ├── color-palette-css-array.html │ ├── color-palette-css-list.html │ ├── color-palette-iadd.html │ ├── color-palette-reverse.html │ ├── color-palette-rgb-tuples.html │ ├── color-palette-rgba-tuples.html │ ├── color-palette.html │ ├── color-scale-axes-categorical-colormap.svg │ ├── color-scale-axes-linear-colormap.svg │ ├── color-scale-canvas-diagonal.svg │ ├── color-scale-canvas-vertical.svg │ ├── color-scale-matrix-default-colormap.svg │ ├── color-scale-matrix-linear-colormap.svg │ ├── color-spread.html │ ├── color-swatch.html │ ├── colormap-empty-domain-ones.html │ ├── colormap-empty-domain-zeros.html │ ├── data-table.html │ ├── ellipse-basic.svg │ ├── ellipse-custom-color.svg │ ├── ellipse-custom-opacity.svg │ ├── ellipse-custom-style.svg │ ├── ellipse-log-y-axis.svg │ ├── ellipse-multiple.svg │ ├── ellipse-rotated.svg │ ├── ellipse-title.svg │ ├── graph-ba-graph-default-layout.svg │ ├── graph-ba-graph-disconnected-vertices-fruchterman-reingold-layout.svg │ ├── graph-ba-graph-eades-layout.svg │ ├── graph-ba-graph-explicit-coordinates.svg │ ├── graph-ba-graph-fruchterman-reingold-curved-edges-layout.svg │ ├── graph-ba-graph-fruchterman-reingold-layout.svg │ ├── graph-ba-graph-graphviz-layout.svg │ ├── graph-ba-graph-random-layout.svg │ ├── graph-prufer-tree-buchheim-layout.svg │ ├── graph-prufer-tree-default-layout.svg │ ├── graph-prufer-tree-eades-layout.svg │ ├── graph-prufer-tree-fruchterman-reingold-layout.svg │ ├── graph-prufer-tree-graphviz-layout.svg │ ├── graph-prufer-tree-random-layout.svg │ ├── graph-shared-layout-graph.svg │ ├── graph-shared-layout-subgraph.svg │ ├── graph-source-target-array-loop-curved.svg │ ├── graph-source-target-array-loop.svg │ ├── graph-source-target-array.svg │ ├── image-non-square-numpy-8-bit-L-colormap.svg │ ├── image-non-square-numpy-8-bit-L.svg │ ├── image-numpy-1-bit-L.svg │ ├── image-numpy-8-bit-L-colormap.svg │ ├── image-numpy-8-bit-L.svg │ ├── image-numpy-8-bit-LA.svg │ ├── image-numpy-8-bit-RGB.svg │ ├── image-numpy-8-bit-RGBA.svg │ ├── legend-boundary-bars.svg │ ├── legend-boundary-fills.svg │ ├── legend-magnitude-bars.svg │ ├── legend-magnitude-fills.svg │ ├── legend-plots.svg │ ├── legend-scatterplots.svg │ ├── linear-luma-plots.svg │ ├── matrix-custom-colormap.svg │ ├── matrix-custom-labels.svg │ ├── matrix-data-range.svg │ ├── matrix-default.svg │ ├── matrix-right-bottom-locators.svg │ ├── opacity-broadcast-bars-one-opacity.svg │ ├── opacity-broadcast-bars-per-datum-opacities.svg │ ├── opacity-broadcast-bars-per-series-opacities.svg │ ├── opacity-broadcast-bars-single-series-per-datum-opacities.svg │ ├── opacity-broadcast-fills-one-opacity.svg │ ├── opacity-broadcast-fills-per-series-opacities.svg │ ├── opacity-broadcast-hlines-one-opacity.svg │ ├── opacity-broadcast-hlines-per-datum-opacities.svg │ ├── opacity-broadcast-plots-one-opacity.svg │ ├── opacity-broadcast-plots-per-series-opacities.svg │ ├── opacity-broadcast-rects-one-opacity.svg │ ├── opacity-broadcast-rects-per-datum-opacities.svg │ ├── opacity-broadcast-scatterplots-one-opacity.svg │ ├── opacity-broadcast-scatterplots-per-datum-opacities.svg │ ├── opacity-broadcast-scatterplots-per-series-opacities.svg │ ├── opacity-broadcast-text-one-opacity.svg │ ├── opacity-broadcast-text-per-datum-opacities.svg │ ├── opacity-broadcast-vlines-one-opacity.svg │ ├── opacity-broadcast-vlines-per-datum-opacities.svg │ ├── scatterplot-one-variable.svg │ ├── style-stroke-dasharray.svg │ ├── table-cell-content.svg │ ├── table-cell-style.svg │ ├── table-center-justification.svg │ ├── table-column-cell-style.svg │ ├── table-column-offsets.svg │ ├── table-column-row-style.svg │ ├── table-column-style.svg │ ├── table-convenience-api.svg │ ├── table-custom-column-widths.svg │ ├── table-defaults.svg │ ├── table-delete-first-column.svg │ ├── table-delete-first-row.svg │ ├── table-delete-last-column.svg │ ├── table-delete-last-row.svg │ ├── table-delete-middle-column.svg │ ├── table-delete-middle-row.svg │ ├── table-doubled-line-separation.svg │ ├── table-doubled-lines.svg │ ├── table-embedded-plots.svg │ ├── table-four-rows-three-columns.svg │ ├── table-full-grid.svg │ ├── table-grid-styles.svg │ ├── table-header-content.svg │ ├── table-header-style.svg │ ├── table-hlines.svg │ ├── table-insert-body-column-after-2.svg │ ├── table-insert-body-column-before-0.svg │ ├── table-insert-body-row-after-2.svg │ ├── table-insert-body-row-before-0.svg │ ├── table-insert-bottom-row-after-2.svg │ ├── table-insert-bottom-row-before-0.svg │ ├── table-insert-left-column-after-2.svg │ ├── table-insert-left-column-before-0.svg │ ├── table-insert-right-column-after-2.svg │ ├── table-insert-right-column-before-0.svg │ ├── table-insert-top-row-after-2.svg │ ├── table-insert-top-row-before-0.svg │ ├── table-label.svg │ ├── table-left-justification.svg │ ├── table-merge-cells-0-2-0-2.svg │ ├── table-merge-cells-2-4-2-4.svg │ ├── table-merge-cells-6-8-6-8.svg │ ├── table-merge-top-left-0-3-0-3.svg │ ├── table-multiple-axes.svg │ ├── table-nulls.svg │ ├── table-right-justification.svg │ ├── table-row-cell-style.svg │ ├── table-row-style.svg │ ├── table-units.svg │ ├── table-vlines.svg │ ├── table-without-header.svg │ ├── text-alignment-baselines.svg │ ├── text-anchor-default.svg │ ├── text-anchor-end.svg │ ├── text-anchor-middle.svg │ ├── text-anchor-shift-angled.svg │ ├── text-anchor-shift-negative.svg │ ├── text-anchor-shift-positive.svg │ ├── text-anchor-start.svg │ ├── text-baseline-shift-angled.svg │ ├── text-baseline-shift-negative.svg │ ├── text-baseline-shift-positive.svg │ ├── text-font-family-courier.svg │ ├── text-font-family-helvetica.svg │ ├── text-font-family-monospace.svg │ ├── text-font-family-sans-serif.svg │ ├── text-font-family-serif.svg │ ├── text-font-family-times.svg │ ├── text-rich-text-ampersand.svg │ ├── text-rich-text-bold-italic.svg │ ├── text-rich-text-bold.svg │ ├── text-rich-text-brackets.svg │ ├── text-rich-text-code.svg │ ├── text-rich-text-hyperlink-style.svg │ ├── text-rich-text-hyperlink-target.svg │ ├── text-rich-text-hyperlink.svg │ ├── text-rich-text-italic.svg │ ├── text-rich-text-line-break.svg │ ├── text-rich-text-nested-break.svg │ ├── text-rich-text-small.svg │ ├── text-rich-text-subscript.svg │ ├── text-rich-text-superscript.svg │ ├── text-vertical-alignment-bottom.svg │ ├── text-vertical-alignment-first-baseline.svg │ ├── text-vertical-alignment-last-baseline.svg │ ├── text-vertical-alignment-middle.svg │ ├── text-vertical-alignment-top.svg │ ├── tick-locator-basic.svg │ ├── tick-locator-default.svg │ ├── tick-locator-explicit-labels.svg │ ├── tick-locator-explicit-locations-labels.svg │ ├── tick-locator-explicit-locations.svg │ ├── tick-locator-extended.svg │ ├── tick-locator-heckbert.svg │ ├── tick-locator-null.svg │ ├── tick-locator-timestamp-10-minute.svg │ ├── tick-locator-timestamp-10-second.svg │ ├── tick-locator-timestamp-15-minute.svg │ ├── tick-locator-timestamp-15-second.svg │ ├── tick-locator-timestamp-4-hour.svg │ ├── tick-locator-timestamp-5-minute.svg │ ├── tick-locator-timestamp-5-second.svg │ ├── tick-locator-timestamp-daily-timezone.svg │ ├── tick-locator-timestamp-day.svg │ ├── tick-locator-timestamp-days-interval.svg │ ├── tick-locator-timestamp-hour.svg │ ├── tick-locator-timestamp-minute.svg │ ├── tick-locator-timestamp-month.svg │ ├── tick-locator-timestamp-quarter.svg │ ├── tick-locator-timestamp-second.svg │ ├── tick-locator-timestamp-three-hour-interval.svg │ ├── tick-locator-timestamp-twelve-minute-interval.svg │ ├── tick-locator-timestamp-twelve-second-interval.svg │ ├── tick-locator-timestamp-two-century-interval.svg │ ├── tick-locator-timestamp-two-day-interval.svg │ ├── tick-locator-timestamp-two-decade-interval.svg │ ├── tick-locator-timestamp-two-millenium-interval.svg │ ├── tick-locator-timestamp-two-month-interval.svg │ ├── tick-locator-timestamp-two-quarter-interval.svg │ ├── tick-locator-timestamp-two-week-interval.svg │ ├── tick-locator-timestamp-two-year-interval.svg │ ├── tick-locator-timestamp-week.svg │ ├── tick-locator-timestamp-year.svg │ ├── title-broadcast-bars-one-title.svg │ ├── title-broadcast-bars-per-datum-titles.svg │ ├── title-broadcast-bars-per-series-titles.svg │ ├── title-broadcast-bars-single-series-per-datum-titles.svg │ ├── title-broadcast-fills-one-title.svg │ ├── title-broadcast-fills-per-series-titles.svg │ ├── title-broadcast-hlines-one-title.svg │ ├── title-broadcast-hlines-per-datum-titles.svg │ ├── title-broadcast-plots-one-title.svg │ ├── title-broadcast-plots-per-datum-titles.svg │ ├── title-broadcast-plots-per-series-per-datum-titles.svg │ ├── title-broadcast-plots-per-series-titles.svg │ ├── title-broadcast-rects-one-title.svg │ ├── title-broadcast-rects-per-datum-titles.svg │ ├── title-broadcast-scatterplots-one-title.svg │ ├── title-broadcast-scatterplots-per-datum-titles.svg │ ├── title-broadcast-scatterplots-per-series-titles.svg │ ├── title-broadcast-text-one-title.svg │ ├── title-broadcast-text-per-datum-titles.svg │ ├── title-broadcast-vlines-one-title.svg │ ├── title-broadcast-vlines-per-datum-titles.svg │ ├── unicode-canvas-text.svg │ ├── unicode-cartesian-label.svg │ ├── unicode-cartesian-text.svg │ ├── unicode-cartesian-tick-labels.svg │ ├── unicode-cartesian-x-label.svg │ └── unicode-cartesian-y-label.svg ├── scatterplot-visualization.feature ├── steps │ ├── administrivia.py │ ├── backend.py │ ├── bar-visualization.py │ ├── browser.py │ ├── canvas.py │ ├── cartesian-coordinates.py │ ├── color-broadcasting.py │ ├── color-scale.py │ ├── color.py │ ├── colormap.py │ ├── common.py │ ├── data-table.py │ ├── data.py │ ├── documentation.py │ ├── ellipse-visualization.py │ ├── fill-visualization.py │ ├── format.py │ ├── graph-visualization.py │ ├── image-visualization.py │ ├── legends.py │ ├── log-scale-axes.py │ ├── matrix-visualization.py │ ├── opacity-broadcasting.py │ ├── plot-visualization.py │ ├── projection.py │ ├── rectangle-visualization.py │ ├── scatterplot-visualization.py │ ├── style.py │ ├── table-visualization.py │ ├── test.py │ ├── testing.py │ ├── text.py │ ├── tick-locator.py │ ├── title-broadcasting.py │ ├── toyplot-8-L.png │ ├── toyplot-8-LA.png │ ├── toyplot-8-RGB.png │ ├── toyplot-8-RGBA.png │ ├── unicode.py │ └── units.py ├── style.feature ├── table-visualization.feature ├── text.feature ├── tick-locator.feature ├── title-broadcasting.feature ├── unicode.feature └── units.feature ├── notebooks ├── .gitignore ├── axes-palette.ipynb ├── cardinalities.ipynb ├── categorical-palette.ipynb ├── config-size.ipynb ├── crazy-colormap-tricks.ipynb ├── custom-marks.ipynb ├── data-storage.ipynb ├── dolphins.gml ├── ellipses.ipynb ├── error-bars.ipynb ├── experimental │ ├── boxcat.py │ ├── domcat.py │ ├── graphcat-etree-attributes.ipynb │ ├── graphcat-etree-children.ipynb │ └── graphcat-etree-layout.ipynb ├── gantt-chart.ipynb ├── graph-api.ipynb ├── graph-coordinate-sharing.ipynb ├── graph-incremental-layout.ipynb ├── graph-markers.ipynb ├── graph-vertex-labels.ipynb ├── grouped-bars.ipynb ├── horizontal-legends.ipynb ├── hyperlinks.ipynb ├── karate.paj ├── label-location.ipynb ├── layout-margins.ipynb ├── legends.ipynb ├── matrix-plus-labels.ipynb ├── matrix-titles.ipynb ├── mouse-coordinates.ipynb ├── pandas-integration.ipynb ├── pandas-timestamps.ipynb ├── plotting-infinities-1.pdf ├── plotting-infinities-2.pdf ├── plotting-infinities-3.pdf ├── plotting-infinities-4.pdf ├── plotting-infinities-data.pdf ├── plotting-infinities.ipynb ├── scatterplot-hyperlinks.ipynb ├── scatterplot-range-issue.ipynb ├── scene-graph-test.ipynb ├── scene-graph-usage.ipynb ├── shared-axis-test.ipynb ├── spatial.ipynb ├── style-colors.ipynb ├── table-hyperlinks.ipynb ├── table-iteration.ipynb ├── text-animation.ipynb ├── text-hyperlinks.ipynb ├── text-layout-shift.ipynb ├── text-markers.ipynb ├── text-vs-marker-alignment.ipynb ├── tick-label-digits.ipynb ├── tick-repellent.ipynb ├── timestamp-timezones.ipynb └── violin-plot-alternative.ipynb ├── pyproject.toml ├── regression.py └── toyplot ├── __init__.py ├── bitmap.py ├── broadcast.py ├── browser.py ├── canvas.py ├── cars.csv ├── color.py ├── community-assigned.csv ├── community-edges.csv ├── community-truth.csv ├── commute.csv ├── config.py ├── coordinates.py ├── data.py ├── deliveries.csv ├── font.py ├── format.py ├── hou.py ├── html.py ├── layout.py ├── locator.py ├── mark.py ├── marker.py ├── pdf.py ├── png.py ├── projection.py ├── reportlab ├── __init__.py ├── pdf.py └── png.py ├── require.py ├── scenegraph.py ├── style.py ├── svg.py ├── temperatures.csv ├── text.py ├── transform.py └── units.py /.github/workflows/regression-tests.yml: -------------------------------------------------------------------------------- 1 | name: Regression tests 2 | 3 | on: 4 | push: 5 | branches: [ main, remove-animation ] 6 | pull_request: 7 | branches: [ main ] 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | strategy: 13 | fail-fast: false 14 | matrix: 15 | python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"] 16 | numpy-version: ["numpy<2.0.0", "numpy>=2.0.0"] 17 | exclude: 18 | - python-version: "3.8" 19 | numpy-version: "numpy>=2.0.0" 20 | 21 | steps: 22 | - uses: actions/checkout@v4 23 | - name: Setup Python ${{ matrix.python-version }} 24 | uses: actions/setup-python@v5 25 | with: 26 | python-version: ${{ matrix.python-version }} 27 | - name: Install Dependencies 28 | run: | 29 | sudo apt-get install ffmpeg ghostscript 30 | python -m pip install --upgrade pip 31 | pip install coveralls 32 | pip install "${{ matrix.numpy-version }}" 33 | pip install .[all] 34 | - name: Run tests 35 | run: | 36 | coverage run --source toyplot -m behave --tags=~wip --logging-level INFO --no-logcapture 37 | coverage report 38 | - name: Upload coverage to Coveralls 39 | run: coveralls --service=github 40 | env: 41 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 42 | - name: Archive failed tests 43 | if: ${{ always() }} 44 | uses: actions/upload-artifact@v4 45 | with: 46 | name: failed 47 | path: features/failed 48 | if-no-files-found: ignore 49 | 50 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | .DS_Store 3 | .cover 4 | .coverage 5 | .ipynb_checkpoints 6 | build 7 | dist 8 | features/backends 9 | features/diffs 10 | features/failed 11 | opsnr.stt 12 | rerun_failing.features 13 | tests/diffs 14 | tests/failed 15 | toyplot.egg-info 16 | -------------------------------------------------------------------------------- /.readthedocs.yaml: -------------------------------------------------------------------------------- 1 | # Read the Docs configuration file for Sphinx projects 2 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details 3 | 4 | # Required 5 | version: 2 6 | 7 | # Set the OS, Python version and other tools you might need 8 | build: 9 | os: ubuntu-22.04 10 | tools: 11 | python: "3.11" 12 | # You can also specify other tool versions: 13 | # nodejs: "20" 14 | # rust: "1.70" 15 | # golang: "1.20" 16 | 17 | # Build documentation in the "docs/" directory with Sphinx 18 | sphinx: 19 | configuration: docs/conf.py 20 | # You can configure Sphinx to use a different builder, for instance use the dirhtml builder for simpler URLs 21 | # builder: "dirhtml" 22 | # Fail on all warnings to avoid broken references 23 | # fail_on_warning: true 24 | 25 | # Optionally build your docs in additional formats such as PDF and ePub 26 | # formats: 27 | # - pdf 28 | # - epub 29 | 30 | # Optional but recommended, declare the Python requirements required 31 | # to build your documentation 32 | # See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html 33 | python: 34 | install: 35 | - requirements: docs/requirements.txt 36 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2014, Sandia Corporation. Under the terms of Contract 2 | DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain 3 | rights in this software. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * Neither the name of Sandia Corporation nor the 13 | names of its contributors may be used to endorse or promote products 14 | derived from this software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | 27 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Welcome! 2 | 3 | 4 | 5 | Welcome to Toyplot, the kid-sized plotting toolkit for Python with grownup-sized goals: 6 | 7 | * Develop beautiful interactive, animated plots that embrace the unique capabilities of electronic publishing and support repoducibility. 8 | * Create the best possible data graphics “out-of-the-box”, maximizing data ink and minimizing chartjunk. 9 | * Provide a clean, minimalist interface that scientists and engineers will love. 10 | 11 | You can see the full Toyplot documentation with tutorials at 12 | https://toyplot.readthedocs.io ... for questions, comments, or suggestions, get 13 | in touch with our team at https://gitter.im/sandialabs/toyplot. 14 | 15 | -------------------------------------------------------------------------------- /artwork/toyplot-256x256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandialabs/toyplot/f71796a34829795deaa65adfa854ddadef0a83d0/artwork/toyplot-256x256.png -------------------------------------------------------------------------------- /artwork/toyplot.lxo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandialabs/toyplot/f71796a34829795deaa65adfa854ddadef0a83d0/artwork/toyplot.lxo -------------------------------------------------------------------------------- /artwork/toyplot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandialabs/toyplot/f71796a34829795deaa65adfa854ddadef0a83d0/artwork/toyplot.png -------------------------------------------------------------------------------- /behave.ini: -------------------------------------------------------------------------------- 1 | [behave] 2 | format = rerun 3 | outfiles = rerun_failing.features 4 | -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- 1 | _build 2 | _static 3 | _templates 4 | _test 5 | *_files 6 | communities.pdf 7 | violin-plot.pdf 8 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line, and also 5 | # from the environment for the first two. 6 | SPHINXOPTS ?= 7 | SPHINXBUILD ?= sphinx-build 8 | SOURCEDIR = . 9 | BUILDDIR = _build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 21 | -------------------------------------------------------------------------------- /docs/arrow.inv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandialabs/toyplot/f71796a34829795deaa65adfa854ddadef0a83d0/docs/arrow.inv -------------------------------------------------------------------------------- /docs/case-studies.rst: -------------------------------------------------------------------------------- 1 | .. _case-studies: 2 | 3 | .. image:: ../artwork/toyplot.png 4 | :width: 200px 5 | :align: right 6 | 7 | Case Studies 8 | ============ 9 | 10 | The following case studies provide more realistic, in-depth examples of how you might use Toyplot as part of a larger workflow: 11 | 12 | .. toctree:: 13 | :maxdepth: 1 14 | 15 | communities-case-study.rst 16 | neural-network-case-study.rst 17 | violin-plots-case-study.rst 18 | -------------------------------------------------------------------------------- /docs/compatibility.rst: -------------------------------------------------------------------------------- 1 | .. _compatibility: 2 | 3 | .. image:: ../artwork/toyplot.png 4 | :width: 200px 5 | :align: right 6 | 7 | Compatibility 8 | ============= 9 | 10 | A quick disclaimer on backwards-compatibility for Toyplot users: 11 | 12 | Toyplot follows the `Semantic Versioning `_ standard for 13 | assigning version numbers in a way that has specific meaning. Toyplot version 14 | numbers use *..* numbering. Releases with different 15 | major API numbers are API incompatible. Minor version numbers signify new 16 | features that are backwards-compatible with the current major version. Patch 17 | numbers indicate bug fixes and documentation changes that are 18 | backwards-compatible with the current major and minor version. 19 | 20 | Python Versions 21 | --------------- 22 | 23 | Past versions of Toyplot supported Python 2 and Python 3 with a single code 24 | base. However, Python 2 has not been maintained since 2020 25 | (https://pythonclock.org), and Toyplot stopped supporting Python 2 on December 26 | 31st, 2018. The Toyplot 0.18 branch was the final release that included Python 27 | 2 support ... beginning with Toyplot 0.19, the portability code was removed and 28 | our automated regression tests are only run using Python 3. Of course, 29 | developers are free to continue working with the 0.18 branch if they need to 30 | support Python 2, and we will consider pull requests for the 0.18 branch if 31 | they arise. 32 | -------------------------------------------------------------------------------- /docs/css/SNL_Stacked_Black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandialabs/toyplot/f71796a34829795deaa65adfa854ddadef0a83d0/docs/css/SNL_Stacked_Black.png -------------------------------------------------------------------------------- /docs/css/toyplot-rtd.css: -------------------------------------------------------------------------------- 1 | .toyplot-color-CategoricalMap, .toyplot-color-DivergingMap, .toyplot-color-LinearMap, .toyplot-color-Palette, .toyplot-color-Swatch, .toyplot-color-Swatches, .toyplot-data-Table 2 | { 3 | margin-bottom: 20px; 4 | } 5 | 6 | div.toyplot 7 | { 8 | margin-bottom: 20px; 9 | } 10 | 11 | footer p 12 | { 13 | background-image: url('SNL_Stacked_Black.png'); 14 | background-position: left center; 15 | background-repeat: no-repeat; 16 | background-size: 150px; 17 | padding: 10px 0 10px 180px; 18 | text-align: left; 19 | font-size: 10pt; 20 | line-height: 12pt; 21 | margin-left: 30px; 22 | margin-right: 30px; 23 | } 24 | 25 | .logo-important 26 | { 27 | margin-top: 100px !important; 28 | } 29 | -------------------------------------------------------------------------------- /docs/css/toyplot.css: -------------------------------------------------------------------------------- 1 | @import url("css/theme.css"); 2 | @import url("toyplot-rtd.css"); 3 | 4 | -------------------------------------------------------------------------------- /docs/documentation-embedding.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandialabs/toyplot/f71796a34829795deaa65adfa854ddadef0a83d0/docs/documentation-embedding.png -------------------------------------------------------------------------------- /docs/ethos.rst: -------------------------------------------------------------------------------- 1 | 2 | .. image:: ../artwork/toyplot.png 3 | :width: 200px 4 | :align: right 5 | 6 | .. _ethos: 7 | 8 | The Toyplot Ethos 9 | ================= 10 | 11 | | *Always look your best.* 12 | | *Share your things.* 13 | | *Play well with others.* 14 | | *Never tell a lie.* 15 | 16 | What began as a quick workaround to produce better figures for some experiments 17 | in machine learning has quickly grown into Toyplot, "the kid-sized plotting toolkit with 18 | grownup-sized goals". In a nutshell, we think that scientists and engineers 19 | should expect more from their plots, from explicit support for 20 | reproducibility and open science to greater clarity and better aesthetics. 21 | 22 | We especially feel that, in an age of ubiquitous electronic media and the web, 23 | it makes little sense to publish using media (like PDF) designed to mimic 24 | the limitations of static paper. Toyplot embraces the standards of the internet - HTML, 25 | SVG, and Javascript - as its primary medium, so we can make useful new 26 | interactions part of the everyday experiences of data graphic users. Because 27 | we're passionate about publishing and sharing results, Toyplot graphics will always be 28 | completely self-contained and embeddable, without the need for a server. All 29 | of the Toyplot graphics you will see in this documentation are live and 30 | interactive, despite the fact that they were created offline in a Jupyter 31 | notebook and passed through several publishing steps on the way to becoming our 32 | documentation. Of course, we provide backends to publish Toyplot figures to 33 | legacy formats including PDF, PNG, and MP4 *(Play well with others)*. 34 | 35 | With most toolkits, interactivity means throwaway features like pan-and-zoom. For 36 | Toyplot, we're exploring simple-but-effective ideas to address the questions a 37 | colleague might ask when viewing a graphic in the real world: "What's the value 38 | at this weird peak?" "Where do those two series cross?" "Can I get a copy of the data?" 39 | We're working on efficient animation that doesn't compromise the quality of your graphic 40 | with compression artifacts; and interactive data cursors that display quantities 41 | of interest and descriptive statistics just by hovering the mouse. And since 42 | the raw data is already implicitly embedded in a graphic, why not support 43 | reproducibility by making it easy to export, so the viewer can work with it 44 | themselves? That's why Toyplot figures can export their underlying raw data 45 | in CSV format *(Share your things)*. 46 | 47 | Last but definitely not least: Toyplot fully embraces principles and best 48 | practices for clarity and aesthetics in data graphics that are well-established 49 | by the visualization community, yet sadly lacking in contemporary plotting 50 | libraries *(Always look your best)*. Toyplot has beautiful color palettes and sensible default styling 51 | that minimize chartjunk and maximize data ink out of the box, not as 52 | afterthoughts or addons. 53 | 54 | -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | .. toyplot documentation master file, created by 2 | sphinx-quickstart on Fri Apr 18 18:22:53 2014. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | .. image:: ../artwork/toyplot.png 7 | :width: 300px 8 | :align: right 9 | 10 | Welcome! 11 | ======== 12 | 13 | Welcome to Toyplot, the kid-sized plotting toolkit for Python with grownup-sized goals: 14 | 15 | * Develop beautiful interactive, animated plots that embrace the unique capabilities of electronic publishing and support reproducibility. 16 | * Create the best possible data graphics "out-of-the-box", maximizing data ink and minimizing chartjunk. 17 | * Provide a clean, minimalist interface that scientists and engineers will love. 18 | 19 | Read more about our ideas for Toyplot and scientific publishing :ref:`here `. 20 | 21 | Documentation 22 | ============= 23 | 24 | .. toctree:: 25 | :maxdepth: 2 26 | 27 | ethos.rst 28 | installation.rst 29 | tutorial.rst 30 | user-guide.rst 31 | case-studies.rst 32 | projects.rst 33 | development.rst 34 | reference.rst 35 | javascript.rst 36 | compatibility.rst 37 | release-notes.rst 38 | support.rst 39 | credits.rst 40 | 41 | Indices and tables 42 | ================== 43 | 44 | * :ref:`genindex` 45 | * :ref:`modindex` 46 | 47 | -------------------------------------------------------------------------------- /docs/installation.rst: -------------------------------------------------------------------------------- 1 | .. image:: ../artwork/toyplot.png 2 | :width: 200px 3 | :align: right 4 | 5 | .. _installation: 6 | 7 | Installation 8 | ============ 9 | 10 | Toyplot 11 | ------- 12 | 13 | To install the latest stable version of Toyplot and its dependencies, use `pip`:: 14 | 15 | $ pip install toyplot 16 | 17 | ... once it completes, you'll be able to use all of Toyplot's core features. 18 | 19 | 20 | Ghostscript 21 | ----------- 22 | 23 | To generate static PNG versions of your Toyplot figures, you'll need 24 | Ghostscript, which can't be installed via pip. If you use `Conda `_ 25 | (which we strongly recommend), you can install it as follows:: 26 | 27 | $ conda install ghostscript 28 | 29 | .. _documentation: 30 | 31 | Documentation 32 | ------------- 33 | 34 | We assume that you'll normally access this documentation online, but if you 35 | want a local copy on your own computer, do the following: 36 | 37 | First, you'll need the `pandoc `_ universal document 38 | converter, which can't be installed with pip ... if you use `Conda `_ 39 | (we cannot recommend it strongly enough), you can install it with the following:: 40 | 41 | $ conda install pandoc 42 | 43 | Once you have pandoc, install Toyplot along with all of the dependencies needed to build the docs:: 44 | 45 | $ pip install toyplot[doc] 46 | 47 | Next, do the following to download a tarball to the current directory 48 | containing all of the Toyplot source code, which includes the documentation:: 49 | 50 | $ pip download toyplot --no-binary=:all: --no-deps 51 | 52 | Now, you can extract the tarball contents and build the documentation (adjust the 53 | following for the version you downloaded):: 54 | 55 | $ tar xzvf toyplot-0.6.1.tar.gz 56 | $ cd toyplot-0.6.1/docs 57 | $ make html 58 | -------------------------------------------------------------------------------- /docs/javascript.rst: -------------------------------------------------------------------------------- 1 | .. image:: ../artwork/toyplot.png 2 | :width: 200px 3 | :align: right 4 | 5 | Javascript API 6 | ============== 7 | 8 | Note that the Javascript API described here is for developers adding new 9 | functionality to Toyplot ... casual Toyplot users will never need to work with 10 | this code. 11 | 12 | .. toctree:: 13 | :maxdepth: 2 14 | 15 | js/toyplot.canvas.id.rst 16 | js/toyplot.canvas.rst 17 | js/toyplot.io.rst 18 | js/toyplot.menus.context.rst 19 | js/toyplot.root.id.rst 20 | js/toyplot.root.rst 21 | js/toyplot.tables.rst 22 | -------------------------------------------------------------------------------- /docs/jet.npy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandialabs/toyplot/f71796a34829795deaa65adfa854ddadef0a83d0/docs/jet.npy -------------------------------------------------------------------------------- /docs/js/toyplot.canvas.id.rst: -------------------------------------------------------------------------------- 1 | toyplot/canvas/id module 2 | ======================== 3 | 4 | .. js:module::toyplot/canvas/id 5 | 6 | The `toyplot/canvas/id` module is a string containing the globally-unique HTML 7 | DOM id for the SVG element containing a Toyplot figure. You can use this id to 8 | reference the SVG element and make changes. For example:: 9 | 10 | context.require(dependencies=["toyplot/canvas/id"], code="""function(canvas_id) 11 | { 12 | var canvas = document.querySelector("#" + canvas_id); 13 | /* Make changes to the figure using canvas. */ 14 | }""") 15 | 16 | -------------------------------------------------------------------------------- /docs/js/toyplot.canvas.rst: -------------------------------------------------------------------------------- 1 | toyplot/canvas module 2 | ===================== 3 | 4 | .. js:module::toyplot/canvas 5 | 6 | The `toyplot/canvas` module is a reference to the SVG element that contains the 7 | figure. For example:: 8 | 9 | context.require(dependencies=["toyplot/canvas"], code="""function(canvas) 10 | { 11 | /* Make changes to the figure using canvas. */ 12 | }""") 13 | 14 | -------------------------------------------------------------------------------- /docs/js/toyplot.io.rst: -------------------------------------------------------------------------------- 1 | toyplot/io module 2 | ================= 3 | 4 | .. js:module::toyplot/io 5 | 6 | The `toyplot/io` module contains functionality for exporting data from the viewer's browser. 7 | 8 | .. js:function:: toyplot/io.save_file(mime_type, charset, data, filename) 9 | 10 | Save data from the viewer's browser to a file. For example:: 11 | 12 | context.require( 13 | dependencies=["toyplot/tables", "toyplot/io"], 14 | code="""function(tables, io) 15 | { 16 | var data = tables.get_csv("my-graph", "vertices"); 17 | io.save_file("text/csv", "utf-8", data, "my-graph-vertices.csv"); 18 | }""") 19 | 20 | Note that the behavior of individual browsers when saving files will vary - 21 | they may-or-may not prompt the user to choose an alternate filename, or 22 | offer to open the file in some other application instead. 23 | 24 | :param mime_type: String MIME type of the data to be saved (e.g. "text/csv"). 25 | :param charset: String character encoding of the data to be saved (e.g. "utf-8"). 26 | :param data: String data to be saved. 27 | :param filename: Suggested filename string to use for saving the data to disk. 28 | 29 | 30 | -------------------------------------------------------------------------------- /docs/js/toyplot.menus.context.rst: -------------------------------------------------------------------------------- 1 | toyplot/menus/context module 2 | ============================ 3 | 4 | .. js:module::toyplot/menus/context 5 | 6 | The `toyplot/menus/context` module provides functionality to display custom 7 | context menu entries when the user right-clicks over a figure. 8 | 9 | .. js:function:: toyplot/menus/context.add_item(label, show, activate) 10 | 11 | Adds a new menu item to the context menu. Each menu item has a label, a 12 | callback to determine when item should be visible, and a callback to 13 | performe some action when the item is activated by the user. Typically, 14 | menu items are added by individual marks, and the visibility callback 15 | will show the item if the mouse pointer was over the mark when the 16 | context menu was opened. For example:: 17 | 18 | context.require( 19 | dependencies["toyplot/menus/context"], 20 | code="""function(menus) 21 | { 22 | // This item will always be visible. 23 | function show() { return true; } 24 | function activate() { console.log("Hello, World!"); } 25 | menus.add_item("Hello World!", show, activate); 26 | }""") 27 | 28 | Note that the Toyplot context menu will not be shown if there are no visible items. When this happens 29 | the system context menu will be shown instead. 30 | 31 | :param label: Human readable string label for the menu item to be added. 32 | :param show: Javascript callback function that will be called before the context menu is opened. 33 | The function must take one argument - the DOM event that is causing the 34 | context menu to be shown (such as a `contextmenu` or `mousedown` 35 | event). The callback should return `true` if the menu item should be 36 | visible, or `false` otherwise. 37 | :param activate: Javascript callback function that will be called if the user selects this item. 38 | -------------------------------------------------------------------------------- /docs/js/toyplot.root.id.rst: -------------------------------------------------------------------------------- 1 | toyplot/root/id module 2 | ====================== 3 | 4 | .. js:module::toyplot/root/id 5 | 6 | The `toyplot/root/id` module is a string containing the globally-unique HTML DOM 7 | id for a Toyplot figure. You can use this id to reference the outer DOM 8 | element that contains the figure. For example:: 9 | 10 | context.require(dependencies=["toyplot/root/id"], code="""function(root_id) 11 | { 12 | var root = document.querySelector("#" + root_id); 13 | /* Make global changes to the figure using root. */ 14 | }""") 15 | 16 | -------------------------------------------------------------------------------- /docs/js/toyplot.root.rst: -------------------------------------------------------------------------------- 1 | toyplot/root module 2 | =================== 3 | 4 | .. js:module::toyplot/root 5 | 6 | The `toyplot/root` module is a reference to the outer DOM element that contains 7 | the figure. For example:: 8 | 9 | context.require(dependencies=["toyplot/root"], code="""function(root) 10 | { 11 | /* Make global changes to the figure using root. */ 12 | }""") 13 | 14 | -------------------------------------------------------------------------------- /docs/js/toyplot.tables.rst: -------------------------------------------------------------------------------- 1 | toyplot/tables module 2 | ===================== 3 | 4 | .. js:module::toyplot/tables 5 | 6 | The `toyplot/tables` module can be used to store tabular data for later retrieval. 7 | 8 | .. js:function:: toyplot/tables.set(owner, key, names, columns) 9 | 10 | Store tabular information, identified by owner and key, for later retrieval. For example:: 11 | 12 | context.require( 13 | dependencies=["toyplot/tables"], 14 | arguments=[mark_id, column_names, columns], 15 | code="""function(tables, mark_id, column_names, columns) 16 | { 17 | tables.store(mark_id, "vertex_data", column_names, columns); 18 | }""") 19 | 20 | :param owner: Unique string id for the object that "owns" the table. 21 | :param key: String key used to disambiguate tables when the owner has more than one. 22 | :param names: Array of string names for each column in the table. 23 | :param columns: Array of value arrays for eacn column in the table. 24 | 25 | 26 | .. js:function:: toyplot/tables.get(owner, key) 27 | 28 | Retrieve a table stored previously using :js:func:`toyplot/tables.set`. For example:: 29 | 30 | context.require( 31 | dependencies=["toyplot/tables"], 32 | arguments=[graph_id], 33 | code="""function(tables, graph_id) 34 | { 35 | console.log(tables.get(graph_id, "vertex_data")); 36 | }""") 37 | 38 | :param owner: Unique string id for the object that "owns" the table. 39 | :param key: String key used to disambiguate tables when the owner has more than one. 40 | 41 | :returns: object containing `names` and `columns` arrays, containing the table column names and column values, respectively. 42 | 43 | -------------------------------------------------------------------------------- /docs/jupyter-embedding.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandialabs/toyplot/f71796a34829795deaa65adfa854ddadef0a83d0/docs/jupyter-embedding.png -------------------------------------------------------------------------------- /docs/numpy.inv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandialabs/toyplot/f71796a34829795deaa65adfa854ddadef0a83d0/docs/numpy.inv -------------------------------------------------------------------------------- /docs/pandas.inv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandialabs/toyplot/f71796a34829795deaa65adfa854ddadef0a83d0/docs/pandas.inv -------------------------------------------------------------------------------- /docs/pillow.inv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandialabs/toyplot/f71796a34829795deaa65adfa854ddadef0a83d0/docs/pillow.inv -------------------------------------------------------------------------------- /docs/projects.rst: -------------------------------------------------------------------------------- 1 | .. _projects: 2 | 3 | .. image:: ../artwork/toyplot.png 4 | :width: 200px 5 | :align: right 6 | 7 | Projects Using Toyplot 8 | ====================== 9 | 10 | The following projects are using Toyplot, either for final rendering or as a rendering back-end for domain-specific visualization: 11 | 12 | Toytree 13 | ------- 14 | 15 | Toytree - http://toytree.readthedocs.io - is a tree manipulation and plotting 16 | library that aims to be rich in features but simple in design, by layering 17 | functionality atop Toyplot. 18 | 19 | -------------------------------------------------------------------------------- /docs/python.inv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandialabs/toyplot/f71796a34829795deaa65adfa854ddadef0a83d0/docs/python.inv -------------------------------------------------------------------------------- /docs/qtconsole-embedding.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandialabs/toyplot/f71796a34829795deaa65adfa854ddadef0a83d0/docs/qtconsole-embedding.png -------------------------------------------------------------------------------- /docs/reference.rst: -------------------------------------------------------------------------------- 1 | .. image:: ../artwork/toyplot.png 2 | :width: 200px 3 | :align: right 4 | 5 | Python API 6 | ========== 7 | 8 | .. toctree:: 9 | :maxdepth: 2 10 | 11 | toyplot.rst 12 | toyplot.bitmap.rst 13 | toyplot.broadcast.rst 14 | toyplot.browser.rst 15 | toyplot.canvas.rst 16 | toyplot.color.rst 17 | toyplot.config.rst 18 | toyplot.coordinates.rst 19 | toyplot.data.rst 20 | toyplot.font.rst 21 | toyplot.format.rst 22 | toyplot.hou.rst 23 | toyplot.html.rst 24 | toyplot.layout.rst 25 | toyplot.locator.rst 26 | toyplot.mark.rst 27 | toyplot.marker.rst 28 | toyplot.pdf.rst 29 | toyplot.png.rst 30 | toyplot.projection.rst 31 | toyplot.reportlab.rst 32 | toyplot.reportlab.pdf.rst 33 | toyplot.reportlab.png.rst 34 | toyplot.require.rst 35 | toyplot.scenegraph.rst 36 | toyplot.style.rst 37 | toyplot.svg.rst 38 | toyplot.text.rst 39 | toyplot.transform.rst 40 | toyplot.units.rst 41 | 42 | -------------------------------------------------------------------------------- /docs/requirements.txt: -------------------------------------------------------------------------------- 1 | custom_inherit 2 | ipython 3 | multipledispatch 4 | nbsphinx 5 | numpy < 2.0.0 6 | pypng 7 | reportlab 8 | sphinx >= 3.5 9 | sphinx_rtd_theme 10 | -------------------------------------------------------------------------------- /docs/support.rst: -------------------------------------------------------------------------------- 1 | .. image:: ../artwork/toyplot.png 2 | :width: 200px 3 | :align: right 4 | 5 | Support 6 | ======= 7 | 8 | The Toyplot documentation: 9 | 10 | * http://toyplot.readthedocs.io 11 | 12 | Visit our GitHub repository for access to source code, test results, issue tracker, and the wiki: 13 | 14 | * http://github.com/sandialabs/toyplot 15 | 16 | Our coverage statistics are updated automatically when modifications are committed: 17 | 18 | * https://coveralls.io/r/sandialabs/toyplot 19 | 20 | For Toyplot questions, comments, or suggestions, get in touch with the team at: 21 | 22 | * https://github.com/sandialabs/toyplot/discussions 23 | 24 | Otherwise, you can contact Tim directly: 25 | 26 | * Timothy M. Shead - `tshead@sandia.gov `_ 27 | -------------------------------------------------------------------------------- /docs/toyplot.bitmap.rst: -------------------------------------------------------------------------------- 1 | toyplot.bitmap module 2 | ===================== 3 | 4 | .. automodule:: toyplot.bitmap 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/toyplot.broadcast.rst: -------------------------------------------------------------------------------- 1 | toyplot.broadcast module 2 | ======================== 3 | 4 | .. automodule:: toyplot.broadcast 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/toyplot.browser.rst: -------------------------------------------------------------------------------- 1 | toyplot.browser module 2 | ====================== 3 | 4 | .. automodule:: toyplot.browser 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/toyplot.canvas.rst: -------------------------------------------------------------------------------- 1 | toyplot.canvas module 2 | ===================== 3 | 4 | .. automodule:: toyplot.canvas 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/toyplot.color.rst: -------------------------------------------------------------------------------- 1 | toyplot.color module 2 | ===================== 3 | 4 | .. automodule:: toyplot.color 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | 9 | -------------------------------------------------------------------------------- /docs/toyplot.config.rst: -------------------------------------------------------------------------------- 1 | toyplot.config module 2 | ===================== 3 | 4 | .. automodule:: toyplot.config 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/toyplot.coordinates.rst: -------------------------------------------------------------------------------- 1 | toyplot.coordinates module 2 | ========================== 3 | 4 | .. automodule:: toyplot.coordinates 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/toyplot.data.rst: -------------------------------------------------------------------------------- 1 | toyplot.data module 2 | =================== 3 | 4 | .. automodule:: toyplot.data 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/toyplot.font.rst: -------------------------------------------------------------------------------- 1 | toyplot.font module 2 | ==================== 3 | 4 | .. automodule:: toyplot.font 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/toyplot.format.rst: -------------------------------------------------------------------------------- 1 | toyplot.format module 2 | ===================== 3 | 4 | .. automodule:: toyplot.format 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/toyplot.hou.rst: -------------------------------------------------------------------------------- 1 | toyplot.hou module 2 | ================== 3 | 4 | .. automodule:: toyplot.hou 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/toyplot.html.rst: -------------------------------------------------------------------------------- 1 | toyplot.html module 2 | =================== 3 | 4 | .. automodule:: toyplot.html 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/toyplot.layout.rst: -------------------------------------------------------------------------------- 1 | toyplot.layout module 2 | ===================== 3 | 4 | .. automodule:: toyplot.layout 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/toyplot.locator.rst: -------------------------------------------------------------------------------- 1 | toyplot.locator module 2 | ====================== 3 | 4 | .. automodule:: toyplot.locator 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/toyplot.mark.rst: -------------------------------------------------------------------------------- 1 | toyplot.mark module 2 | =================== 3 | 4 | .. automodule:: toyplot.mark 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/toyplot.marker.rst: -------------------------------------------------------------------------------- 1 | toyplot.marker module 2 | ===================== 3 | 4 | .. automodule:: toyplot.marker 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/toyplot.pdf.rst: -------------------------------------------------------------------------------- 1 | toyplot.pdf module 2 | ================== 3 | 4 | .. automodule:: toyplot.pdf 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/toyplot.png.rst: -------------------------------------------------------------------------------- 1 | toyplot.png module 2 | ================== 3 | 4 | .. automodule:: toyplot.png 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/toyplot.projection.rst: -------------------------------------------------------------------------------- 1 | toyplot.projection module 2 | ========================= 3 | 4 | .. automodule:: toyplot.projection 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/toyplot.reportlab.pdf.rst: -------------------------------------------------------------------------------- 1 | toyplot.reportlab.pdf module 2 | ============================ 3 | 4 | .. automodule:: toyplot.reportlab.pdf 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/toyplot.reportlab.png.rst: -------------------------------------------------------------------------------- 1 | toyplot.reportlab.png module 2 | ============================ 3 | 4 | .. automodule:: toyplot.reportlab.png 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/toyplot.reportlab.rst: -------------------------------------------------------------------------------- 1 | toyplot.reportlab module 2 | ======================== 3 | 4 | .. automodule:: toyplot.reportlab 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/toyplot.require.rst: -------------------------------------------------------------------------------- 1 | toyplot.require module 2 | ====================== 3 | 4 | .. automodule:: toyplot.require 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/toyplot.rst: -------------------------------------------------------------------------------- 1 | toyplot module 2 | =============== 3 | 4 | .. automodule:: toyplot 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/toyplot.scenegraph.rst: -------------------------------------------------------------------------------- 1 | toyplot.scenegraph module 2 | ========================= 3 | 4 | .. automodule:: toyplot.scenegraph 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/toyplot.style.rst: -------------------------------------------------------------------------------- 1 | toyplot.style module 2 | ==================== 3 | 4 | .. automodule:: toyplot.style 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/toyplot.svg.rst: -------------------------------------------------------------------------------- 1 | toyplot.svg module 2 | ================== 3 | 4 | .. automodule:: toyplot.svg 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/toyplot.text.rst: -------------------------------------------------------------------------------- 1 | toyplot.text module 2 | =================== 3 | 4 | .. automodule:: toyplot.text 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/toyplot.transform.rst: -------------------------------------------------------------------------------- 1 | toyplot.transform module 2 | ======================== 3 | 4 | .. automodule:: toyplot.transform 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/toyplot.units.rst: -------------------------------------------------------------------------------- 1 | toyplot.units module 2 | ==================== 3 | 4 | .. automodule:: toyplot.units 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/user-guide.rst: -------------------------------------------------------------------------------- 1 | .. _user-guide: 2 | 3 | .. image:: ../artwork/toyplot.png 4 | :width: 200px 5 | :align: right 6 | 7 | User Guide 8 | ========== 9 | 10 | Contents: 11 | 12 | .. toctree:: 13 | :maxdepth: 2 14 | 15 | canvas-layout.ipynb 16 | cartesian-coordinates.ipynb 17 | colors.ipynb 18 | color-mapping.ipynb 19 | convenience-api.ipynb 20 | data-tables.ipynb 21 | ellipse-visualization.ipynb 22 | embedding.ipynb 23 | graph-visualization.ipynb 24 | image-visualization.ipynb 25 | interaction.ipynb 26 | labels-and-legends.ipynb 27 | log-scales.ipynb 28 | markers.ipynb 29 | matrix-visualization.ipynb 30 | numberline-coordinates.ipynb 31 | null-data.ipynb 32 | rendering.ipynb 33 | table-coordinates.ipynb 34 | text.ipynb 35 | tick-locators.ipynb 36 | units.ipynb 37 | -------------------------------------------------------------------------------- /features/administrivia.feature: -------------------------------------------------------------------------------- 1 | Feature: Administrivia 2 | 3 | Scenario: 4 | Given all Toyplot sources. 5 | Then every source must contain a copyright notice. 6 | 7 | -------------------------------------------------------------------------------- /features/backend.feature: -------------------------------------------------------------------------------- 1 | Feature: Backend 2 | Scenario Outline: Render a canvas with a backend 3 | Given that the backend is available 4 | And a default canvas 5 | And a set of cartesian axes 6 | And a sample plot 7 | Then the canvas can be rendered to 8 | 9 | Examples: 10 | | backend | output | 11 | | toyplot.html | an html file | 12 | | toyplot.html | an html buffer | 13 | | toyplot.html | a returned html dom | 14 | | toyplot.pdf | a pdf file | 15 | | toyplot.pdf | a pdf buffer | 16 | | toyplot.pdf | a returned pdf document | 17 | | toyplot.png | a png file | 18 | | toyplot.png | a png buffer | 19 | | toyplot.png | a returned png document | 20 | | toyplot.png | a 200 pixel wide png document | 21 | | toyplot.png | a 150 pixel high png document | 22 | | toyplot.png | a half scale png document | 23 | | toyplot.reportlab.pdf | a pdf file | 24 | | toyplot.reportlab.pdf | a pdf buffer | 25 | | toyplot.reportlab.pdf | a returned pdf document | 26 | | toyplot.reportlab.png | a png file | 27 | | toyplot.reportlab.png | a png buffer | 28 | | toyplot.reportlab.png | a returned png document | 29 | | toyplot.svg | an svg file | 30 | | toyplot.svg | an svg buffer | 31 | | toyplot.svg | a returned svg dom | 32 | 33 | -------------------------------------------------------------------------------- /features/bar-visualization.feature: -------------------------------------------------------------------------------- 1 | Feature: Bar visualization 2 | Scenario Outline: Bar visualization 3 | Given a default canvas 4 | And a set of cartesian axes 5 | And 6 | Then the figure should match the reference image 7 | 8 | Examples: 9 | | scenario | reference | 10 | | bars-boundaries-masked-nan | bars-boundaries-masked-nan | 11 | | bars-histogram | bars-histogram | 12 | | bars-magnitudes-masked-nan | bars-magnitudes-masked-nan | 13 | | bars-n-boundaries-along-y | bars-n-boundaries-along-y | 14 | | bars-n-boundaries-centers | bars-n-boundaries-centers | 15 | | bars-n-boundaries-edges | bars-n-boundaries-edges | 16 | | bars-n-boundaries-titles | bars-n-boundaries-titles | 17 | | bars-n-boundaries | bars-n-boundaries | 18 | | bars-n-magnitudes-along-y | bars-n-magnitudes-along-y | 19 | | bars-n-magnitudes-centers | bars-n-magnitudes-centers | 20 | | bars-n-magnitudes-edges | bars-n-magnitudes-edges | 21 | | bars-n-magnitudes-symmetric | bars-n-magnitudes-symmetric | 22 | | bars-n-magnitudes-titles | bars-n-magnitudes-titles | 23 | | bars-n-magnitudes-wiggle | bars-n-magnitudes-wiggle | 24 | | bars-n-magnitudes | bars-n-magnitudes | 25 | | bars-one-boundary-centers | bars-one-boundary-centers | 26 | | bars-one-boundary-edges | bars-one-boundary-edges | 27 | | bars-one-boundary | bars-one-boundary | 28 | | bars-one-magnitude-centers | bars-one-magnitude-centers | 29 | | bars-one-magnitude-edges | bars-one-magnitude-edges | 30 | | bars-one-magnitude | bars-one-magnitude | 31 | 32 | 33 | -------------------------------------------------------------------------------- /features/browser.feature: -------------------------------------------------------------------------------- 1 | Feature: Web browser display 2 | Scenario: Display a Toyplot canvas in a web browser 3 | Given a sample Toyplot canvas, the canvas can be displayed in a web browser 4 | 5 | -------------------------------------------------------------------------------- /features/canvas.feature: -------------------------------------------------------------------------------- 1 | Feature: Canvas 2 | Scenario Outline: Canvas layouts 3 | Given a canvas with a border 4 | Then axes can be added to the canvas using . 5 | And the figure should match the reference image 6 | 7 | Examples: 8 | | layout | reference | 9 | | the default layout | canvas-layout-default | 10 | | explicit bounds | canvas-layout-bounds | 11 | | grid layout | canvas-layout-grid | 12 | | corner layout | canvas-layout-corner | 13 | | rect layout | canvas-layout-rect | 14 | 15 | Scenario: Canvas Jupyter HTML 16 | Given a default canvas 17 | And a set of cartesian axes 18 | And a sample plot 19 | Then the canvas can be rendered in Jupyter as HTML 20 | 21 | Scenario: Canvas Jupyter PNG 22 | Given a default canvas 23 | And a set of cartesian axes 24 | And a sample plot 25 | Then the canvas can be rendered in Jupyter as a PNG image 26 | 27 | Scenario: Canvas numberline layout 28 | Given a canvas with a border 29 | Then numberlines can be added to the canvas using relative coordinates 30 | And the figure should match the canvas-layout-numberline-relative reference image 31 | -------------------------------------------------------------------------------- /features/color-conversion.feature: -------------------------------------------------------------------------------- 1 | Feature: Color conversion 2 | Scenario Outline: Conversion from css 3 | When toyplot.color.css receives 4 | Then toyplot.color.css should return 5 | 6 | Examples: 7 | | input | output | 8 | | red | (1, 0, 0, 1) | 9 | | Red | (1, 0, 0, 1) | 10 | | RED | (1, 0, 0, 1) | 11 | | aqua | (0, 1, 1, 1) | 12 | | ivory | (1, 1, 240/255, 1) | 13 | | transparent | (0, 0, 0, 0) | 14 | | #f0f | (1, 0, 1, 1) | 15 | | #F0F | (1, 0, 1, 1) | 16 | | #F8F | (1, 8/15, 1, 1) | 17 | | #ff00ff | (1, 0, 1, 1) | 18 | | #FF00ff | (1, 0, 1, 1) | 19 | | #FF88ff | (1, 8/15, 1, 1) | 20 | | rgb(255, 128, 3) | (255/255, 128/255, 3/255, 1) | 21 | | rgb(76%, 32%, 89%) | (.76, .32, .89, 1) | 22 | | rgba(255, 128, 3, 0.45) | (255/255, 128/255, 3/255, 0.45) | 23 | | rgba(76%, 32%, 89%, .76) | (.76, .32, .89, .76) | 24 | | hsl(0, 100%, 50%) | (1, 0, 0, 1) | 25 | | hsla(0, 100%, 50%, 0.32) | (1, 0, 0, 0.32) | 26 | | baloney | None | 27 | 28 | Scenario Outline: Conversion to css 29 | When toyplot.color.to_css receives 30 | Then toyplot.color.to_css should return 31 | 32 | Examples: 33 | | input | output | 34 | | toyplot.color.rgba(1, .5, .4, 1) | rgba(100.0%,50.0%,40.0%,1.000) | 35 | -------------------------------------------------------------------------------- /features/color-scale.feature: -------------------------------------------------------------------------------- 1 | Feature: Color scale 2 | Scenario Outline: Canvas color scales 3 | Given a default canvas 4 | And a 5 | Then a can be added to the canvas 6 | And the figure should match the reference image 7 | 8 | Examples: 9 | | colormap | scale | reference | 10 | | linear colormap | vertical color scale | color-scale-canvas-vertical | 11 | | linear colormap | diagonal color scale | color-scale-canvas-diagonal | 12 | 13 | Scenario Outline: Canvas color scales 14 | Given a default canvas 15 | And a set of cartesian axes 16 | And a 17 | Then a can be added to the axes 18 | And the figure should match the reference image 19 | 20 | Examples: 21 | | colormap | scale | reference | 22 | | linear colormap | color scale | color-scale-axes-linear-colormap | 23 | | categorical colormap | color scale | color-scale-axes-categorical-colormap | 24 | 25 | Scenario Outline: Matrix visualization color scales 26 | Given a default canvas 27 | Then a can be added to a matrix visualization 28 | And the figure should match the reference image 29 | 30 | Examples: 31 | | scale | reference | 32 | | color scale with default colormap | color-scale-matrix-default-colormap | 33 | | color scale with linear colormap | color-scale-matrix-linear-colormap | 34 | 35 | -------------------------------------------------------------------------------- /features/colormap.feature: -------------------------------------------------------------------------------- 1 | Feature: Colormap 2 | 3 | Scenario: Linear color map 4 | Given a linear color map 5 | Then the linear color map can be rendered as ipython html 6 | And the linear color map can map scalar values to toyplot colors 7 | And the linear color map can map scalar values to css colors 8 | And the color map domain can be changed 9 | 10 | Scenario: Diverging color map 11 | Given a collection of diverging color maps 12 | Then each diverging color map can be rendered as ipython html 13 | 14 | Scenario: Default diverging color map 15 | When the user creates a default diverging color map 16 | Then the default diverging color map can be rendered as ipython html 17 | 18 | Scenario: Custom diverging color map 19 | When the user creates a custom diverging color map 20 | Then the custom diverging color map can be rendered as ipython html 21 | 22 | Scenario: Diverging color map colors 23 | When the user creates a default diverging color map with domain 24 | Then individual values can be mapped to colors by the diverging color map 25 | 26 | Scenario: Diverging color map css 27 | When the user creates a default diverging color map with domain 28 | Then individual values can be mapped to css colors by the diverging color map 29 | 30 | Scenario: Categorical color map 31 | Given a categorical color map, the map can be rendered as ipython html 32 | 33 | Scenario: Categorial color map colors 34 | Given a categorical color map, multiple colors can be returned by index 35 | 36 | Scenario: Categorical color map color 37 | Given a categorical color map, individual colors can be returned by index 38 | 39 | Scenario: Categorical color map css 40 | Given a categorical color map, individual css colors can be returned by index 41 | 42 | Scenario Outline: Empty domain 43 | Given a linear color map without a domain 44 | And colormap values 45 | When mapping colors without a domain 46 | Then the color swatches should match the reference html 47 | 48 | Examples: 49 | | values | reference | 50 | | [0, 0, 0] | colormap-empty-domain-zeros | 51 | | [1, 1, 1] | colormap-empty-domain-ones | 52 | 53 | 54 | -------------------------------------------------------------------------------- /features/data.feature: -------------------------------------------------------------------------------- 1 | Feature: Data manipulation 2 | Scenario: Contiguous data 3 | Given an array, contiguous regions of the array can be consolidated 4 | 5 | -------------------------------------------------------------------------------- /features/documentation.feature: -------------------------------------------------------------------------------- 1 | Feature: Documentation 2 | 3 | Scenario: Module documentation 4 | Given all public Toyplot modules 5 | And the Toyplot reference documentation 6 | Then every module must have a section in the reference documentation 7 | And every section in the reference documentation must match a module 8 | 9 | Scenario: Notebook documentation 10 | Given the Toyplot documentation notebooks 11 | Then every notebook runs without error 12 | -------------------------------------------------------------------------------- /features/ellipse-visualization.feature: -------------------------------------------------------------------------------- 1 | Feature: Ellipse visualization 2 | Scenario Outline: Ellipse visualization 3 | Given a default canvas 4 | And a set of cartesian axes 5 | And 6 | Then the figure should match the reference image 7 | 8 | Examples: 9 | | scenario | reference | 10 | | a basic ellipse | ellipse-basic | 11 | | a rotated ellipse | ellipse-rotated | 12 | | an ellipse with log y axis | ellipse-log-y-axis | 13 | | an ellipse with a title | ellipse-title | 14 | | an ellipse with a custom color | ellipse-custom-color | 15 | | an ellipse with a custom opacity | ellipse-custom-opacity | 16 | | an ellipse with a custom style | ellipse-custom-style | 17 | | multiple ellipses | ellipse-multiple | 18 | 19 | 20 | -------------------------------------------------------------------------------- /features/image-visualization.feature: -------------------------------------------------------------------------------- 1 | Feature: Image visualization 2 | Scenario Outline: Render an image 3 | Given 4 | And a default canvas 5 | And a canvas background color 6 | When the image is added to the canvas 7 | Then the figure should match the reference image 8 | 9 | Examples: 10 | | image | reference | 11 | | a numpy 1 bit L image | image-numpy-1-bit-L | 12 | | a numpy 8 bit L image | image-numpy-8-bit-L | 13 | | a numpy 8 bit L image with colormap | image-numpy-8-bit-L-colormap | 14 | | a numpy 8 bit LA image | image-numpy-8-bit-LA | 15 | | a numpy 8 bit RGB image | image-numpy-8-bit-RGB | 16 | | a numpy 8 bit RGBA image | image-numpy-8-bit-RGBA | 17 | | a pillow 8 bit L image | image-numpy-8-bit-L | 18 | | a pillow 8 bit L image with colormap | image-numpy-8-bit-L-colormap | 19 | | a pillow 8 bit RGB image | image-numpy-8-bit-RGB | 20 | | a pillow 8 bit RGBA image | image-numpy-8-bit-RGBA | 21 | | a non-square numpy 8 bit L image | image-non-square-numpy-8-bit-L | 22 | | a non-square numpy 8 bit L image with colormap | image-non-square-numpy-8-bit-L-colormap | 23 | 24 | -------------------------------------------------------------------------------- /features/legends.feature: -------------------------------------------------------------------------------- 1 | Feature: Legends 2 | Scenario Outline: Render legends 3 | Given a default canvas 4 | And a set of cartesian axes 5 | And 6 | And the marks are used to create a legend 7 | Then the figure should match the reference image 8 | 9 | Examples: 10 | | scenario | reference | 11 | | the data is rendered as boundary bars | legend-boundary-bars | 12 | | the data is rendered as magnitude bars | legend-magnitude-bars | 13 | | the data is rendered as boundary fills | legend-boundary-fills | 14 | | the data is rendered as magnitude fills | legend-magnitude-fills | 15 | | the data is rendered as plots | legend-plots | 16 | | the data is rendered as scatterplots | legend-scatterplots | 17 | 18 | -------------------------------------------------------------------------------- /features/line-visualization.feature: -------------------------------------------------------------------------------- 1 | Feature: Line visualization 2 | Scenario: Annotation Lines 3 | When adding default line marks to axes 4 | Then the line marks should be treated as annotations. 5 | 6 | Scenario: Data Lines 7 | When adding data line marks to axes 8 | Then the line marks should be treated as data. 9 | -------------------------------------------------------------------------------- /features/log-scale-axes.feature: -------------------------------------------------------------------------------- 1 | Feature: Log scale axes 2 | Scenario Outline: Log scale axes 3 | Given 4 | And a default canvas 5 | And 6 | When plotting x, x with markers 7 | Then the figure should match the reference image 8 | 9 | Examples: 10 | | data | axes | reference | 11 | | values from -1000 to -1 | log 10 axes on x and y | axes-log-scale-negative-1000-negative-1 | 12 | | values from -1000 to -0.01 | log 10 axes on x and y | axes-log-scale-negative-1000-negative-0.01 | 13 | | values from -1000 to 0 | log 10 axes on x and y | axes-log-scale-negative-1000-zero | 14 | | values from -1000 to 0.5 | log 10 axes on x and y | axes-log-scale-negative-1000-0.5 | 15 | | values from 0 to 1000 | log 10 axes on x and y | axes-log-scale-zero-1000 | 16 | | values from 0.01 to 1000 | log 10 axes on x and y | axes-log-scale-0.01-1000 | 17 | | values from 1 to 1000 | log 10 axes on x and y | axes-log-scale-1-1000 | 18 | | values from -0.5 to 1000 | log 10 axes on x and y | axes-log-scale-negative-0.5-1000 | 19 | | values from -1000 to 1000 | log 10 axes on x and y | axes-log-scale-negative-1000-1000 | 20 | | values from -1000 to -1 | log 2 axes on x and y | axes-log-2-scale-negative-1000-negative-1 | 21 | | values from 1 to 1000 | log 2 axes on x and y | axes-log-2-scale-1-1000 | 22 | | values from -1000 to 1000 | log 2 axes on x and y | axes-log-2-scale-negative-1000-1000 | 23 | | values from -1000 to 1000 | log 10 axes on x and y with custom format | axes-log-10-scale-negative-1000-1000-custom-format | 24 | 25 | 26 | Scenario Outline: Log scale axes with restricted domain 27 | Given 28 | And a default canvas 29 | And 30 | When plotting the values with bars 31 | Then the figure should match the reference image 32 | 33 | Examples: 34 | | data | axes | reference | 35 | | squared values from 0 to 10 | log 10 axes on y with domain min 10 | axes-log-10-scale-0-100-domain-min-10 | 36 | | squared values from -10 to 0 | log 10 axes on y with domain max -10 | axes-log-10-scale-negative-100-0-domain-max-negative-10 | 37 | 38 | -------------------------------------------------------------------------------- /features/matrix-visualization.feature: -------------------------------------------------------------------------------- 1 | Feature: Matrix visualization 2 | Scenario Outline: Matrix visualization 3 | Given a default canvas 4 | And a matrix 5 | And a matrix visualization 6 | Then the figure should match the reference image 7 | 8 | Examples: 9 | | scenario | reference | 10 | | created with the convenience API | matrix-default | 11 | | created with the standard API | matrix-default | 12 | | created with a custom colormap | matrix-custom-colormap | 13 | | created with custom labels | matrix-custom-labels | 14 | | created with right and bottom index locators | matrix-right-bottom-locators | 15 | 16 | Scenario: Matrix data range 17 | Given a default canvas 18 | And a set of cartesian axes 19 | And a matrix 20 | And a matrix visualization without left labels 21 | Then the figure should match the matrix-data-range reference image 22 | 23 | -------------------------------------------------------------------------------- /features/opacity-broadcasting.feature: -------------------------------------------------------------------------------- 1 | Feature: Opacity Broadcasting 2 | Scenario Outline: Opacity broadcasting use-cases 3 | Given a default canvas 4 | And a set of cartesian axes 5 | And a set of diverging series 6 | And a set of per-series opacity values 7 | And a set of per-datum opacity values 8 | Then can be rendered with 9 | And the figure should match the reference image 10 | 11 | Examples: 12 | | mark | opacity | reference | 13 | | bars | one explicit opacity | opacity-broadcast-bars-one-opacity | 14 | | bars | per-series opacities | opacity-broadcast-bars-per-series-opacities | 15 | | bars | per-datum opacities | opacity-broadcast-bars-per-datum-opacities | 16 | | fills | one explicit opacity | opacity-broadcast-fills-one-opacity | 17 | | fills | per-series opacities | opacity-broadcast-fills-per-series-opacities | 18 | | hlines | one explicit opacity | opacity-broadcast-hlines-one-opacity | 19 | | hlines | per-datum opacities | opacity-broadcast-hlines-per-datum-opacities | 20 | | plots | one explicit opacity | opacity-broadcast-plots-one-opacity | 21 | | plots | per-series opacities | opacity-broadcast-plots-per-series-opacities | 22 | | rects | one explicit opacity | opacity-broadcast-rects-one-opacity | 23 | | rects | per-datum opacities | opacity-broadcast-rects-per-datum-opacities | 24 | | scatterplots | one explicit opacity | opacity-broadcast-scatterplots-one-opacity | 25 | | scatterplots | per-series opacities | opacity-broadcast-scatterplots-per-series-opacities | 26 | | scatterplots | per-datum opacities | opacity-broadcast-scatterplots-per-datum-opacities | 27 | | text | one explicit opacity | opacity-broadcast-text-one-opacity | 28 | | text | per-datum opacities | opacity-broadcast-text-per-datum-opacities | 29 | | vlines | one explicit opacity | opacity-broadcast-vlines-one-opacity | 30 | | vlines | per-datum opacities | opacity-broadcast-vlines-per-datum-opacities | 31 | 32 | Scenario: Per-datum opacity broadcasting with one series 33 | Given a default canvas 34 | And a set of cartesian axes 35 | Then bars can be rendered with a single series and per-datum opacities 36 | And the figure should match the opacity-broadcast-bars-single-series-per-datum-opacities reference image 37 | 38 | -------------------------------------------------------------------------------- /features/plot-visualization.feature: -------------------------------------------------------------------------------- 1 | Feature: Plot visualization 2 | Scenario Outline: Plot visualization 3 | Given a default canvas 4 | And a set of cartesian axes 5 | And 6 | Then the figure should match the reference image 7 | 8 | Examples: 9 | | scenario | reference | 10 | | axes-plot-masked-nan | axes-plot-masked-nan | 11 | | axes-plot-n-variables-along-y | axes-plot-n-variables-along-y | 12 | | axes-plot-n-variables-x | axes-plot-n-variables-x | 13 | | axes-plot-n-variables | axes-plot-n-variables | 14 | | axes-plot-one-variable-x | axes-plot-one-variable-x | 15 | | axes-plot-one-variable | axes-plot-one-variable | 16 | 17 | 18 | -------------------------------------------------------------------------------- /features/projection.feature: -------------------------------------------------------------------------------- 1 | Feature: Projection 2 | Scenario Outline: Round trip projection 3 | Given A projection with and 4 | Then should project to 5 | 6 | Examples: 7 | | type | domain | range | value | projection | 8 | | linear | 0, 1 | 0, 100 | 0 | 0 | 9 | | linear | 0, 1 | 0, 100 | 0.5 | 50 | 10 | | linear | 0, 1 | 0, 100 | 1 | 100 | 11 | | log10 | 1, 100 | 0, 100 | 1 | 0 | 12 | | log10 | 1, 100 | 0, 100 | 10 | 50 | 13 | | log10 | 1, 100 | 0, 100 | 100 | 100 | 14 | | log10 | -100, 100 | 0, 100 | -100 | 0 | 15 | | log10 | -100, 100 | 0, 100 | 0 | 50 | 16 | | log10 | -100, 100 | 0, 100 | 100 | 100 | 17 | -------------------------------------------------------------------------------- /features/rectangle-visualization.feature: -------------------------------------------------------------------------------- 1 | Feature: Rectangle visualization 2 | Scenario Outline: Rectangle visualization 3 | Given a default canvas 4 | And a set of cartesian axes 5 | And 6 | Then the figure should match the reference image 7 | 8 | Examples: 9 | | scenario | reference | 10 | | axes-rect-singular-along-y | axes-rect-singular-along-y | 11 | | axes-rect-singular | axes-rect-singular | 12 | | axes-rect | axes-rect | 13 | 14 | 15 | -------------------------------------------------------------------------------- /features/reference/axes-cartesian-show.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /features/reference/canvas-layout-numberline-relative.svg: -------------------------------------------------------------------------------- 1 | -0.50.00.5 -------------------------------------------------------------------------------- /features/reference/color-brewer-Accent.html: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /features/reference/color-brewer-BlueGreen.html: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /features/reference/color-brewer-BlueGreenBrown.html: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /features/reference/color-brewer-BlueGreenYellow.html: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /features/reference/color-brewer-BluePurple.html: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /features/reference/color-brewer-BlueRed.html: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /features/reference/color-brewer-BlueYellowRed.html: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /features/reference/color-brewer-Blues.html: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /features/reference/color-brewer-BrownOrangeYellow.html: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /features/reference/color-brewer-Dark2.html: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /features/reference/color-brewer-GrayRed.html: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /features/reference/color-brewer-GreenBlue.html: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /features/reference/color-brewer-GreenBluePurple.html: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /features/reference/color-brewer-GreenYellow.html: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /features/reference/color-brewer-GreenYellowRed.html: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /features/reference/color-brewer-Greens.html: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /features/reference/color-brewer-Greys.html: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /features/reference/color-brewer-Oranges.html: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /features/reference/color-brewer-Paired.html: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /features/reference/color-brewer-Pastel1.html: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /features/reference/color-brewer-Pastel2.html: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /features/reference/color-brewer-PinkGreen.html: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /features/reference/color-brewer-PurpleBlue.html: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /features/reference/color-brewer-PurpleGreen.html: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /features/reference/color-brewer-PurpleOrange.html: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /features/reference/color-brewer-PurpleRed.html: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /features/reference/color-brewer-Purples.html: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /features/reference/color-brewer-RedOrange.html: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /features/reference/color-brewer-RedOrangeYellow.html: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /features/reference/color-brewer-RedPurple.html: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /features/reference/color-brewer-Reds.html: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /features/reference/color-brewer-Set1.html: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /features/reference/color-brewer-Set2.html: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /features/reference/color-brewer-Set3.html: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /features/reference/color-brewer-Spectral.html: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /features/reference/color-brewer-count.html: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /features/reference/color-brewer-reverse.html: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /features/reference/color-brewer.html: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /features/reference/color-categorical-map.html: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /features/reference/color-diverging-map-BlueBrown.html: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /features/reference/color-diverging-map-BlueRed.html: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /features/reference/color-diverging-map-GreenRed.html: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /features/reference/color-diverging-map-PurpleGreen.html: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /features/reference/color-diverging-map-PurpleOrange.html: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /features/reference/color-diverging-map-custom.html: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /features/reference/color-diverging-map.html: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /features/reference/color-linear-map.html: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /features/reference/color-palette-add.html: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /features/reference/color-palette-css-array.html: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /features/reference/color-palette-css-list.html: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /features/reference/color-palette-iadd.html: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /features/reference/color-palette-reverse.html: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /features/reference/color-palette-rgb-tuples.html: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /features/reference/color-palette-rgba-tuples.html: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /features/reference/color-palette.html: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /features/reference/color-spread.html: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /features/reference/color-swatch.html: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /features/reference/colormap-empty-domain-ones.html: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /features/reference/colormap-empty-domain-zeros.html: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /features/reference/data-table.html: -------------------------------------------------------------------------------- 1 |
foobarbaz
00.191519450379blue
10.62210877104red
20.437727739007red
30.785358583714red
40.779975808119green
50.272592605283red
60.276464255143green
70.801872177535blue
80.958139353684blue
90.875932634742blue
-------------------------------------------------------------------------------- /features/reference/image-non-square-numpy-8-bit-L.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /features/reference/image-numpy-1-bit-L.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /features/reference/table-four-rows-three-columns.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /features/reference/unicode-canvas-text.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /features/reference/unicode-cartesian-tick-labels.svg: -------------------------------------------------------------------------------- 1 | -0.50.00.5 -------------------------------------------------------------------------------- /features/scatterplot-visualization.feature: -------------------------------------------------------------------------------- 1 | Feature: Scatterplot visualization 2 | Scenario Outline: Scatterplot visualization 3 | Given a default canvas 4 | And a set of cartesian axes 5 | And 6 | Then the figure should match the reference image 7 | 8 | Examples: 9 | | scenario | reference | 10 | | axes-scatterplot-markers | axes-scatterplot-markers | 11 | | axes-scatterplot-n-variables-along-y | axes-scatterplot-n-variables-along-y | 12 | | axes-scatterplot-n-variables-x | axes-scatterplot-n-variables-x | 13 | | axes-scatterplot-n-variables | axes-scatterplot-n-variables | 14 | | axes-scatterplot-one-variable-fill | axes-scatterplot-one-variable-fill | 15 | | axes-scatterplot-one-variable-x | axes-scatterplot-one-variable-x | 16 | | axes-scatterplot-one-variable | axes-scatterplot-one-variable | 17 | | axes-scatterplot-singular | axes-scatterplot-singular | 18 | | scatterplot-one-variable | scatterplot-one-variable | 19 | 20 | 21 | -------------------------------------------------------------------------------- /features/steps/administrivia.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014, Sandia Corporation. Under the terms of Contract 2 | # DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain 3 | # rights in this software. 4 | 5 | from behave import * 6 | 7 | import os 8 | import pkgutil 9 | import subprocess 10 | import sys 11 | 12 | root_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..")) 13 | docs_dir = os.path.join(root_dir, "docs") 14 | package_dir = os.path.join(root_dir, "toyplot") 15 | 16 | copyright_notice = """# Copyright 2014, Sandia Corporation. Under the terms of Contract 17 | # DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain 18 | # rights in this software. 19 | 20 | """ 21 | 22 | @given(u'all Toyplot sources.') 23 | def step_impl(context): 24 | context.sources = [] 25 | for directory, subdirectories, filenames in os.walk(root_dir): 26 | for filename in filenames: 27 | if os.path.splitext(filename)[1] not in [".py"]: 28 | continue 29 | if os.path.basename(directory) == "_test": 30 | continue 31 | 32 | context.sources.append(os.path.join(directory, filename)) 33 | context.sources = sorted(context.sources) 34 | 35 | @then(u'every source must contain a copyright notice.') 36 | def step_impl(context): 37 | for source in context.sources: 38 | with open(source, "r") as stream: 39 | if not stream.read().startswith(copyright_notice): 40 | raise AssertionError("%s missing copyright notice." % source) 41 | 42 | -------------------------------------------------------------------------------- /features/steps/browser.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014, Sandia Corporation. Under the terms of Contract 2 | # DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain 3 | # rights in this software. 4 | 5 | from behave import * 6 | 7 | import test 8 | import numpy 9 | import sys 10 | import toyplot.browser 11 | import unittest.mock 12 | import webbrowser 13 | 14 | 15 | @given(u'a sample Toyplot canvas, the canvas can be displayed in a web browser') 16 | def step_impl(context): 17 | canvas, axes, mark = toyplot.plot(numpy.sin(numpy.linspace(0, 10))) 18 | with unittest.mock.patch("webbrowser.open") as webbrowser_open: 19 | toyplot.browser.show(canvas) 20 | test.assert_equal(webbrowser_open.call_count, 1) 21 | test.assert_true( 22 | webbrowser_open.call_args[0][0].startswith("file://")) 23 | test.assert_equal(webbrowser_open.call_args[1]["new"], 1) 24 | test.assert_equal(webbrowser_open.call_args[1]["autoraise"], True) 25 | 26 | 27 | -------------------------------------------------------------------------------- /features/steps/color-scale.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014, Sandia Corporation. Under the terms of Contract 2 | # DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain 3 | # rights in this software. 4 | 5 | from behave import * 6 | 7 | import numpy 8 | import toyplot.color 9 | 10 | @given(u'a linear colormap') 11 | def step_impl(context): 12 | context.colormap = toyplot.color.brewer.map("BlueRed", domain_min=0, domain_max=1) 13 | 14 | @given(u'a categorical colormap') 15 | def step_impl(context): 16 | context.colormap = toyplot.color.CategoricalMap() 17 | 18 | @then(u'a vertical color scale can be added to the canvas') 19 | def step_impl(context): 20 | context.canvas.color_scale(context.colormap, x1=100, x2=100, y1="-10%", y2="10%") 21 | 22 | @then(u'a diagonal color scale can be added to the canvas') 23 | def step_impl(context): 24 | context.canvas.color_scale(context.colormap, x1=100, x2=-100, y1=-100, y2=100) 25 | 26 | @then(u'a color scale can be added to the axes') 27 | def step_impl(context): 28 | context.axes.color_scale(context.colormap) 29 | 30 | @then(u'a color scale with default colormap can be added to a matrix visualization') 31 | def step_impl(context): 32 | numpy.random.seed(1234) 33 | values = numpy.random.normal(size=(10, 10)) 34 | context.canvas.matrix(values, colorshow=True) 35 | 36 | @then(u'a color scale with linear colormap can be added to a matrix visualization') 37 | def step_impl(context): 38 | numpy.random.seed(1234) 39 | values = numpy.random.normal(size=(10, 10)) 40 | colormap = toyplot.color.brewer.map("BlueGreenBrown", domain_min=-2, domain_max=2) 41 | context.canvas.matrix((values, colormap), colorshow=True) 42 | 43 | -------------------------------------------------------------------------------- /features/steps/colormap.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014, Sandia Corporation. Under the terms of Contract 2 | # DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain 3 | # rights in this software. 4 | 5 | from behave import * 6 | 7 | import testing 8 | 9 | import numpy 10 | import toyplot.color 11 | 12 | @given(u'a linear color map without a domain') 13 | def step_impl(context): 14 | context.colormap = toyplot.color.brewer.map("BlueYellowRed") 15 | 16 | 17 | @given(u'colormap values {}') 18 | def step_impl(context, values): 19 | context.values = eval(values) 20 | 21 | 22 | @when(u'mapping colors without a domain') 23 | def step_impl(context): 24 | context.colors = context.colormap.colors(context.values) 25 | 26 | 27 | @then(u'the color swatches should match the {} reference html') 28 | def step_impl(context, reference): 29 | testing.assert_html_equal(toyplot.color._jupyter_color_swatches(context.colors), reference) 30 | 31 | -------------------------------------------------------------------------------- /features/steps/common.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014, Sandia Corporation. Under the terms of Contract 2 | # DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain 3 | # rights in this software. 4 | 5 | from behave import * 6 | 7 | import numpy 8 | import toyplot 9 | 10 | import testing 11 | 12 | 13 | @given(u'a default canvas') 14 | def step_impl(context): 15 | context.canvas = toyplot.Canvas() 16 | 17 | 18 | @given(u'a set of cartesian axes') 19 | def step_impl(context): 20 | context.axes = context.canvas.cartesian() 21 | 22 | 23 | @given(u'a sample plot') 24 | def step_impl(context): 25 | context.axes.plot(numpy.sin(numpy.linspace(0, 10))) 26 | 27 | 28 | @then(u'the figure should match the {reference} reference image') 29 | def step_impl(context, reference): 30 | show_diff = context.config.userdata.getbool("show_diff", default=True) 31 | testing.assert_canvas_equal(context.canvas, reference, show_diff=show_diff) 32 | 33 | -------------------------------------------------------------------------------- /features/steps/data.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014, Sandia Corporation. Under the terms of Contract 2 | # DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain 3 | # rights in this software. 4 | 5 | from behave import * 6 | import test 7 | import numpy.testing 8 | import toyplot.data 9 | 10 | @given(u'an array, contiguous regions of the array can be consolidated') 11 | def step_impl(context): 12 | array = [1, 1, 2, 2, 2, 3, 4, 2, 2] 13 | begin, end, values = toyplot.data.contiguous(array) 14 | numpy.testing.assert_array_equal(begin, [0, 2, 5, 6, 7]) 15 | numpy.testing.assert_array_equal(end, [2, 5, 6, 7, 9]) 16 | numpy.testing.assert_array_equal(values, [1, 2, 3, 4, 2]) 17 | 18 | -------------------------------------------------------------------------------- /features/steps/ellipse-visualization.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014, Sandia Corporation. Under the terms of Contract 2 | # DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain 3 | # rights in this software. 4 | 5 | from behave import * 6 | 7 | import numpy 8 | import toyplot.locator 9 | 10 | def _set_square_domain(context, size): 11 | context.axes.x.domain.min = -size 12 | context.axes.x.domain.max = size 13 | context.axes.y.domain.min = -size 14 | context.axes.y.domain.max = size 15 | 16 | 17 | @given(u'a basic ellipse') 18 | def step_impl(context): 19 | _set_square_domain(context, 20) 20 | context.axes.ellipse(0, 0, 20, 10) 21 | 22 | 23 | @given(u'a rotated ellipse') 24 | def step_impl(context): 25 | _set_square_domain(context, 20) 26 | context.axes.ellipse(0, 0, 20, 10, 30) 27 | 28 | 29 | @given(u'an ellipse with log y axis') 30 | def step_impl(context): 31 | _set_square_domain(context, 20) 32 | context.axes.y.scale = "log" 33 | context.axes.ellipse(0, 0, 20, 10, 30) 34 | 35 | 36 | @given(u'an ellipse with a title') 37 | def step_impl(context): 38 | _set_square_domain(context, 20) 39 | context.axes.ellipse(0, 0, 20, 10, 30, title="An ellipse.") 40 | 41 | 42 | @given(u'an ellipse with a custom style') 43 | def step_impl(context): 44 | _set_square_domain(context, 20) 45 | context.axes.ellipse(0, 0, 20, 10, 30, style={"stroke": "crimson", "fill": "none"}) 46 | 47 | 48 | @given(u'an ellipse with a custom color') 49 | def step_impl(context): 50 | _set_square_domain(context, 20) 51 | context.axes.ellipse(0, 0, 20, 10, 30, color="crimson") 52 | 53 | 54 | @given(u'an ellipse with a custom opacity') 55 | def step_impl(context): 56 | _set_square_domain(context, 20) 57 | context.axes.ellipse(0, 0, 20, 10, 30, opacity=0.5) 58 | 59 | 60 | @given(u'multiple ellipses') 61 | def step_impl(context): 62 | _set_square_domain(context, 20) 63 | context.axes.ellipse([-10, 10], [0, 0], [5, 5], [2.5, 2.5], [30, -30], color=["crimson", "royalblue"]) 64 | 65 | -------------------------------------------------------------------------------- /features/steps/format.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014, Sandia Corporation. Under the terms of Contract 2 | # DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain 3 | # rights in this software. 4 | 5 | from behave import * 6 | 7 | import test 8 | import numpy.testing 9 | import toyplot.format 10 | 11 | 12 | @given(u'an instance of toyplot.format.BasicFormatter') 13 | def step_impl(context): 14 | context.formatter = toyplot.format.BasicFormatter() 15 | 16 | 17 | @given(u'an instance of toyplot.format.BasicFormatter with nanshow off') 18 | def step_impl(context): 19 | context.formatter = toyplot.format.BasicFormatter(nanshow=False) 20 | 21 | 22 | @given(u'an instance of toyplot.format.FloatFormatter') 23 | def step_impl(context): 24 | context.formatter = toyplot.format.FloatFormatter() 25 | 26 | 27 | @given(u'an instance of toyplot.format.UnitFormatter using {units}') 28 | def step_impl(context, units): 29 | context.formatter = toyplot.format.UnitFormatter(units=eval(units)) 30 | 31 | 32 | @given(u'an instance of toyplot.format.CurrencyFormatter using {currency}') 33 | def step_impl(context, currency): 34 | context.formatter = toyplot.format.CurrencyFormatter(curr=eval(currency)) 35 | 36 | 37 | @then(u'formatting {value} should produce {output}') 38 | def step_impl(context, value, output): 39 | value = eval(value) 40 | output = eval(output) 41 | prefix, separator, suffix = context.formatter.format(value) 42 | test.assert_equal(prefix, output[0]) 43 | test.assert_equal(separator, output[1]) 44 | test.assert_equal(suffix, output[2]) 45 | 46 | -------------------------------------------------------------------------------- /features/steps/legends.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014, Sandia Corporation. Under the terms of Contract 2 | # DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain 3 | # rights in this software. 4 | 5 | from behave import * 6 | import test 7 | import numpy 8 | 9 | def sample_data(): 10 | data = [] 11 | data.append(numpy.column_stack((numpy.linspace(0, 1), numpy.linspace(0, 1) ** 2))) 12 | data.append(numpy.linspace(0, 1) ** 3) 13 | return data 14 | 15 | 16 | @given(u'the data is rendered as boundary bars') 17 | def step_impl(context): 18 | context.marks = [context.axes.bars(data, baseline=None) for data in sample_data()] 19 | 20 | 21 | @given(u'the data is rendered as boundary fills') 22 | def step_impl(context): 23 | context.marks = [context.axes.fill(data, baseline=None) for data in sample_data()] 24 | 25 | 26 | @given(u'the data is rendered as magnitude bars') 27 | def step_impl(context): 28 | context.marks = [context.axes.bars(data, baseline="symmetric") for data in sample_data()] 29 | 30 | 31 | @given(u'the data is rendered as magnitude fills') 32 | def step_impl(context): 33 | context.marks = [context.axes.fill(data, baseline="symmetric") for data in sample_data()] 34 | 35 | 36 | @given(u'the data is rendered as plots') 37 | def step_impl(context): 38 | context.marks = [context.axes.plot(data) for data in sample_data()] 39 | 40 | 41 | @given(u'the data is rendered as scatterplots') 42 | def step_impl(context): 43 | context.marks = [context.axes.scatterplot(data) for data in sample_data()] 44 | 45 | 46 | @given(u'the marks are used to create a legend') 47 | def step_impl(context): 48 | entries = [("Mark %s" % index, mark) for index, mark in enumerate(context.marks)] 49 | table = context.canvas.legend(entries, corner=("top-left", 50, 100, 25 * len(entries))) 50 | table.cells.grid.hlines[...] = "single" 51 | table.cells.grid.vlines[...] = "single" 52 | 53 | 54 | -------------------------------------------------------------------------------- /features/steps/matrix-visualization.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014, Sandia Corporation. Under the terms of Contract 2 | # DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain 3 | # rights in this software. 4 | 5 | from behave import * 6 | 7 | import numpy 8 | import toyplot.locator 9 | 10 | @given(u'a matrix') 11 | def step_impl(context): 12 | numpy.random.seed(1234) 13 | context.matrix = numpy.random.normal(size=(10, 10)) 14 | 15 | @given(u'a matrix visualization created with the convenience API') 16 | def step_impl(context): 17 | context.canvas, context.table = toyplot.matrix(context.matrix) 18 | 19 | @given(u'a matrix visualization created with the standard API') 20 | def step_impl(context): 21 | context.table = context.canvas.matrix(context.matrix) 22 | 23 | @given(u'a matrix visualization without left labels') 24 | def step_impl(context): 25 | context.table = context.canvas.matrix(context.matrix, lshow=False) 26 | 27 | @given(u'a matrix visualization created with a custom palette') 28 | def step_impl(context): 29 | palette = toyplot.color.brewer.palette("BlueGreenBrown") 30 | context.table = context.canvas.matrix((context.matrix, palette)) 31 | 32 | @given(u'a matrix visualization created with a custom colormap') 33 | def step_impl(context): 34 | palette = toyplot.color.brewer.palette("BlueGreenBrown") 35 | colormap = toyplot.color.LinearMap(palette, domain_min=-1, domain_max=1) 36 | context.table = context.canvas.matrix((context.matrix, colormap)) 37 | 38 | @given(u'a matrix visualization created with custom labels') 39 | def step_impl(context): 40 | context.table = context.canvas.matrix(context.matrix, tlabel="Top", blabel="Bottom", llabel="Left", rlabel="Right", rshow=True, bshow=True) 41 | 42 | @given(u'a matrix visualization created with right and bottom index locators') 43 | def step_impl(context): 44 | context.table = context.canvas.matrix(context.matrix, rlocator=toyplot.locator.Integer(), blocator=toyplot.locator.Integer()) 45 | 46 | -------------------------------------------------------------------------------- /features/steps/plot-visualization.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014, Sandia Corporation. Under the terms of Contract 2 | # DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain 3 | # rights in this software. 4 | 5 | from behave import * 6 | 7 | import collections 8 | 9 | import test 10 | import numpy.testing 11 | import toyplot 12 | 13 | 14 | @given(u'axes-plot-masked-nan') 15 | def step_impl(context): 16 | x = numpy.linspace(0, 2 * numpy.pi, 51) 17 | y = numpy.ma.column_stack(( 18 | 1 + 0.5 * numpy.sin(x), 19 | 1 + 0.5 * numpy.cos(x), 20 | 1 + 0.2 * numpy.sin(2 * x), 21 | )) 22 | y[8:18, 0] = numpy.nan 23 | y[33:43, 1] = numpy.ma.masked 24 | 25 | context.axes.plot(x, y, marker="o") 26 | 27 | 28 | @given(u'axes-plot-n-variables-along-y') 29 | def step_impl(context): 30 | numpy.random.seed(1234) 31 | observations = numpy.random.normal(loc=1, size=(25, 100)) 32 | series = numpy.column_stack((numpy.min(observations, axis=1), numpy.mean( 33 | observations, axis=1), numpy.max(observations, axis=1))) 34 | 35 | context.axes.plot(series, along="y") 36 | 37 | 38 | @given(u'axes-plot-n-variables-x') 39 | def step_impl(context): 40 | numpy.random.seed(1234) 41 | observations = numpy.random.normal(loc=1, size=(25, 100)) 42 | x = numpy.linspace(0, 1, len(observations)) 43 | series = numpy.column_stack((numpy.min(observations, axis=1), numpy.mean( 44 | observations, axis=1), numpy.max(observations, axis=1))) 45 | 46 | context.axes.plot(x, series) 47 | 48 | 49 | @given(u'axes-plot-n-variables') 50 | def step_impl(context): 51 | numpy.random.seed(1234) 52 | observations = numpy.random.normal(loc=1, size=(25, 100)) 53 | series = numpy.column_stack((numpy.min(observations, axis=1), numpy.mean( 54 | observations, axis=1), numpy.max(observations, axis=1))) 55 | 56 | context.axes.plot(series) 57 | 58 | 59 | @given(u'axes-plot-one-variable-x') 60 | def step_impl(context): 61 | numpy.random.seed(1234) 62 | observations = numpy.random.normal(loc=1, size=(25, 100)) 63 | x = numpy.linspace(0, 1, len(observations)) 64 | y = numpy.mean(observations, axis=1) 65 | 66 | context.axes.plot(x, y) 67 | 68 | 69 | @given(u'axes-plot-one-variable') 70 | def step_impl(context): 71 | numpy.random.seed(1234) 72 | observations = numpy.random.normal(loc=1, size=(25, 100)) 73 | y = numpy.mean(observations, axis=1) 74 | 75 | context.axes.plot(y) 76 | 77 | 78 | -------------------------------------------------------------------------------- /features/steps/projection.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014, Sandia Corporation. Under the terms of Contract 2 | # DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain 3 | # rights in this software. 4 | 5 | from behave import * 6 | import test 7 | import numpy.testing 8 | 9 | import toyplot.projection 10 | 11 | 12 | @given(u'A linear projection with 0, 1 and 0, 100') 13 | def step_impl(context): 14 | context.projection = toyplot.projection.linear(0, 1, 0, 100) 15 | 16 | 17 | @then(u'0 should project to 0') 18 | def step_impl(context): 19 | test.assert_equal(context.projection(0), 0) 20 | test.assert_equal(context.projection.inverse(0), 0) 21 | 22 | 23 | @then(u'0.5 should project to 50') 24 | def step_impl(context): 25 | test.assert_equal(context.projection(0.5), 50) 26 | test.assert_equal(context.projection.inverse(50), 0.5) 27 | 28 | 29 | @then(u'1 should project to 100') 30 | def step_impl(context): 31 | test.assert_equal(context.projection(1.0), 100) 32 | test.assert_equal(context.projection.inverse(100), 1.0) 33 | 34 | 35 | @given(u'A log10 projection with 1, 100 and 0, 100') 36 | def step_impl(context): 37 | context.projection = toyplot.projection.log(10, 1, 100, 0, 100) 38 | 39 | 40 | @then(u'1 should project to 0') 41 | def step_impl(context): 42 | test.assert_equal(context.projection(1), 0) 43 | test.assert_equal(context.projection.inverse(0), 1) 44 | 45 | 46 | @then(u'10 should project to 50') 47 | def step_impl(context): 48 | test.assert_equal(context.projection(10), 50) 49 | test.assert_equal(context.projection.inverse(50), 10) 50 | 51 | 52 | @then(u'100 should project to 100') 53 | def step_impl(context): 54 | test.assert_equal(context.projection(100), 100) 55 | test.assert_equal(context.projection.inverse(100), 100) 56 | 57 | 58 | @given(u'A log10 projection with -100, 100 and 0, 100') 59 | def step_impl(context): 60 | context.projection = toyplot.projection.log(10, -100, 100, 0, 100) 61 | 62 | 63 | @then(u'-100 should project to 0') 64 | def step_impl(context): 65 | test.assert_equal(context.projection(-100), 0) 66 | test.assert_equal(context.projection.inverse(0), -100) 67 | 68 | 69 | @then(u'0 should project to 50') 70 | def step_impl(context): 71 | test.assert_equal(context.projection(0), 50) 72 | test.assert_equal(context.projection.inverse(50), 0) 73 | -------------------------------------------------------------------------------- /features/steps/rectangle-visualization.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014, Sandia Corporation. Under the terms of Contract 2 | # DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain 3 | # rights in this software. 4 | 5 | from behave import * 6 | 7 | import collections 8 | 9 | import test 10 | import numpy.testing 11 | import toyplot 12 | 13 | 14 | @given(u'axes-rect-singular-along-y') 15 | def step_impl(context): 16 | context.axes.x.domain.min = 0 17 | context.axes.x.domain.max = 1 18 | context.axes.y.domain.min = 0 19 | context.axes.y.domain.max = 1 20 | context.axes.rectangle(0.1, 0.2, 0.3, 0.6, along="y") 21 | 22 | 23 | @given(u'axes-rect-singular') 24 | def step_impl(context): 25 | context.axes.x.domain.min = 0 26 | context.axes.x.domain.max = 1 27 | context.axes.y.domain.min = 0 28 | context.axes.y.domain.max = 1 29 | context.axes.rectangle(0.1, 0.2, 0.3, 0.6) 30 | 31 | 32 | @given(u'axes-rect') 33 | def step_impl(context): 34 | x1 = numpy.arange(1, 10) 35 | x2 = x1 + 0.5 36 | y1 = x1 - 0.5 37 | y2 = x1 ** 1.5 38 | color = x1 39 | title = x1 40 | colormap = toyplot.color.CategoricalMap(toyplot.color.brewer.palette("BlueRed")) 41 | 42 | context.axes.rectangle(x1, x2, y1, y2, color=(color, colormap), title=title) 43 | 44 | 45 | -------------------------------------------------------------------------------- /features/steps/style.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014, Sandia Corporation. Under the terms of Contract 2 | # DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain 3 | # rights in this software. 4 | 5 | from behave import * 6 | 7 | import numpy 8 | import toyplot 9 | 10 | import testing 11 | 12 | @given(u'a sample plot, the plot can be rendered with a dashed line style.') 13 | def step_impl(context): 14 | canvas, axes, mark = toyplot.plot(numpy.linspace(0, 1) ** 2, style={"stroke-dasharray":"5,5"}) 15 | testing.assert_canvas_equal(canvas, "style-stroke-dasharray") 16 | -------------------------------------------------------------------------------- /features/steps/test.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014, Sandia Corporation. Under the terms of Contract 2 | # DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain 3 | # rights in this software. 4 | 5 | 6 | import unittest 7 | 8 | # Repackaging existing tests for PEP-8. 9 | 10 | def assert_almost_equal(first, second, places=7, delta=None, msg=None): 11 | return unittest.TestCase().assertAlmostEqual(first, second, places=places, msg=msg, delta=delta) 12 | 13 | def assert_dict_equal(first, second, msg=None): 14 | return unittest.TestCase().assertDictEqual(first, second, msg) 15 | 16 | def assert_equal(first, second, msg=None): 17 | return unittest.TestCase().assertEqual(first, second, msg) 18 | 19 | def assert_false(expr, msg=None): 20 | return unittest.TestCase().assertFalse(expr, msg) 21 | 22 | def assert_is(first, second, msg=None): 23 | return unittest.TestCase().assertIs(first, second, msg) 24 | 25 | def assert_is_instance(obj, cls, msg=None): 26 | return unittest.TestCase().assertIsInstance(obj, cls, msg) 27 | 28 | def assert_is_none(expr, msg=None): 29 | return unittest.TestCase().assertIsNone(expr, msg) 30 | 31 | def assert_logs(logger=None, level=None): 32 | return unittest.TestCase().assertLogs(logger, level) 33 | 34 | def assert_no_logs(logger=None, level=None): 35 | return unittest.TestCase().assertNoLogs(logger, level) 36 | 37 | def assert_raises(exception): 38 | return unittest.TestCase().assertRaises(exception) 39 | 40 | def assert_sequence_equal(first, second, msg=None, seq_type=None): 41 | return unittest.TestCase().assertSequenceEqual(first, second, msg, seq_type) 42 | 43 | def assert_true(expr, msg=None): 44 | return unittest.TestCase().assertTrue(expr, msg) 45 | -------------------------------------------------------------------------------- /features/steps/toyplot-8-L.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandialabs/toyplot/f71796a34829795deaa65adfa854ddadef0a83d0/features/steps/toyplot-8-L.png -------------------------------------------------------------------------------- /features/steps/toyplot-8-LA.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandialabs/toyplot/f71796a34829795deaa65adfa854ddadef0a83d0/features/steps/toyplot-8-LA.png -------------------------------------------------------------------------------- /features/steps/toyplot-8-RGB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandialabs/toyplot/f71796a34829795deaa65adfa854ddadef0a83d0/features/steps/toyplot-8-RGB.png -------------------------------------------------------------------------------- /features/steps/toyplot-8-RGBA.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandialabs/toyplot/f71796a34829795deaa65adfa854ddadef0a83d0/features/steps/toyplot-8-RGBA.png -------------------------------------------------------------------------------- /features/steps/unicode.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014, Sandia Corporation. Under the terms of Contract 2 | # DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain 3 | # rights in this software. 4 | 5 | from behave import * 6 | 7 | import toyplot 8 | 9 | import testing 10 | 11 | 12 | @when( 13 | u'creating a plot with unicode text in a cartesian axes x label, the plot will match unicode-cartesian-x-label') 14 | def step_impl(context): 15 | axes = context.canvas.cartesian(xlabel=u"L\u0302") 16 | testing.assert_canvas_equal(context.canvas, "unicode-cartesian-x-label") 17 | 18 | 19 | @when( 20 | u'creating a plot with unicode text in a cartesian axes y label, the plot will match unicode-cartesian-y-label') 21 | def step_impl(context): 22 | axes = context.canvas.cartesian(ylabel=u"L\u0302") 23 | testing.assert_canvas_equal(context.canvas, "unicode-cartesian-y-label") 24 | 25 | 26 | @when( 27 | u'creating a plot with unicode text in a cartesian axes label, the plot will match unicode-cartesian-label') 28 | def step_impl(context): 29 | axes = context.canvas.cartesian(label=u"L\u0302") 30 | testing.assert_canvas_equal(context.canvas, "unicode-cartesian-label") 31 | 32 | 33 | @when( 34 | u'creating a plot with unicode text in a cartesian axes tick labels, the plot will match unicode-cartesian-tick-labels') 35 | def step_impl(context): 36 | axes = context.canvas.cartesian() 37 | axes.x.ticks.locator = toyplot.locator.Explicit([0], [u"L\u0302"]) 38 | testing.assert_canvas_equal(context.canvas, "unicode-cartesian-tick-labels") 39 | 40 | 41 | @when( 42 | u'creating a plot with unicode text in a cartesian axes text mark, the plot will match unicode-cartesian-text') 43 | def step_impl(context): 44 | axes = context.canvas.cartesian() 45 | axes.text(0, 0, u"L\u0302") 46 | testing.assert_canvas_equal(context.canvas, "unicode-cartesian-text") 47 | 48 | 49 | @when( 50 | u'creating a plot with unicode text in canvas text, the plot will match unicode-canvas-text') 51 | def step_impl(context): 52 | context.canvas.text(100, 100, u"L\u0302") 53 | testing.assert_canvas_equal(context.canvas, "unicode-canvas-text") 54 | -------------------------------------------------------------------------------- /features/style.feature: -------------------------------------------------------------------------------- 1 | Feature: Style 2 | Scenario: Dashed lines 3 | Given a sample plot, the plot can be rendered with a dashed line style. 4 | -------------------------------------------------------------------------------- /features/unicode.feature: -------------------------------------------------------------------------------- 1 | Feature: Unicode 2 | Scenario Outline: Unicode text 3 | Given a default canvas 4 | When creating a plot with unicode text in , the plot will match 5 | 6 | Examples: 7 | | location | reference | 8 | | a cartesian axes x label | unicode-cartesian-x-label | 9 | | a cartesian axes y label | unicode-cartesian-y-label | 10 | | a cartesian axes label | unicode-cartesian-label | 11 | | a cartesian axes tick labels | unicode-cartesian-tick-labels | 12 | | a cartesian axes text mark | unicode-cartesian-text | 13 | | canvas text | unicode-canvas-text | 14 | 15 | -------------------------------------------------------------------------------- /features/units.feature: -------------------------------------------------------------------------------- 1 | Feature: Units 2 | Scenario Outline: General unit conversion 3 | When converting to the response should be 4 | 5 | Examples: 6 | | input | target | response | 7 | | "0" without default units | points | 0.0 | 8 | | 0 without default units | points | 0.0 | 9 | | 72 without default units | points | raise ValueError | 10 | | 72 with default units pt | in | 1.0 | 11 | | "72pt" | in | 1.0 | 12 | | (72, "pt") | in | 1.0 | 13 | | "100%" without reference | in | raise ValueError | 14 | | "100%" with reference 1.0 | in | 1.0 | 15 | | "40%" with reference 1.0 | in | 0.4 | 16 | | "96px" | in | 1.0 | 17 | | "96px" | pt | 72.0 | 18 | | ".5in" | pt | 36.0 | 19 | | "1in" | cm | 2.54 | 20 | | "1furlong" | in | raise ValueError | 21 | | [] | in | raise ValueError | 22 | | ("72pt",) | in | raise ValueError | 23 | | ("1","cm") | in | raise ValueError | 24 | | (1,2) | in | raise ValueError | 25 | | "1in" | furlong | raise ValueError | 26 | -------------------------------------------------------------------------------- /notebooks/.gitignore: -------------------------------------------------------------------------------- 1 | latex-math-pdf.pdf 2 | test* 3 | texput.* 4 | -------------------------------------------------------------------------------- /notebooks/experimental/domcat.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014, Sandia Corporation. Under the terms of Contract 2 | # DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain 3 | # rights in this software. 4 | 5 | """Proof-of-concept DOM manipulation using Graphcat.""" 6 | 7 | import copy 8 | import io 9 | import xml.etree.ElementTree as xml 10 | 11 | def append_element(graph, name, inputs): 12 | """Graphcat task function that appends one element as a child of another.""" 13 | parent = copy.copy(inputs.getone("parent")) 14 | child = inputs.getone("child") 15 | parent.append(child) 16 | return parent 17 | 18 | 19 | def create_element(tag, attrib={}, **extra): 20 | """Graphcat task function that creates an element.""" 21 | def implementation(graph, name, inputs): 22 | return xml.Element(tag, attrib=attrib, **extra) 23 | return implementation 24 | 25 | 26 | def dump(element, level=0): 27 | """Recursively pretty-print an element and its children.""" 28 | indent = " " * level 29 | attributes = "".join(f" {key}=\"{str(value)}\"" for key, value in element.items()) 30 | if len(element) or element.text: 31 | print(f"{indent}<{element.tag}{attributes}>") 32 | if element.text: 33 | print(f"{indent} {element.text}") 34 | for child in element: 35 | dump(child, level+1) 36 | print(f"{indent}") 37 | else: 38 | print(f"{indent}<{element.tag}{attributes}/>") 39 | 40 | 41 | def set_attribute(key, value): 42 | """Graphcat task function that sets an element attribute.""" 43 | def implementation(graph, name, inputs): 44 | original = inputs.getone(None) 45 | modified = xml.Element(original.tag, attrib=original.attrib) 46 | for child in original: 47 | modified.append(child) 48 | modified.set(key, value) 49 | return modified 50 | return implementation 51 | 52 | 53 | def tostring(element): 54 | """Convert an element to a compact string representation.""" 55 | attributes = "".join(f" {key}=\"{str(value)}\"" for key, value in element.items()) 56 | if len(element) or element.text: 57 | result = f"<{element.tag}{attributes}>" 58 | if element.text: 59 | result += element.text 60 | for child in element: 61 | result += tostring(child) 62 | return result + f"" 63 | return f"<{element.tag}{attributes}/>" 64 | 65 | -------------------------------------------------------------------------------- /notebooks/karate.paj: -------------------------------------------------------------------------------- 1 | *Vertices 34 2 | 1 "1" 3 | 2 "2" 4 | 3 "3" 5 | 4 "4" 6 | 5 "5" 7 | 6 "6" 8 | 7 "7" 9 | 8 "8" 10 | 9 "9" 11 | 10 "10" 12 | 11 "11" 13 | 12 "12" 14 | 13 "13" 15 | 14 "14" 16 | 15 "15" 17 | 16 "16" 18 | 17 "17" 19 | 18 "18" 20 | 19 "19" 21 | 20 "20" 22 | 21 "21" 23 | 22 "22" 24 | 23 "23" 25 | 24 "24" 26 | 25 "25" 27 | 26 "26" 28 | 27 "27" 29 | 28 "28" 30 | 29 "29" 31 | 30 "30" 32 | 31 "31" 33 | 32 "32" 34 | 33 "33" 35 | 34 "34" 36 | *Edges 37 | 1 2 38 | 1 3 39 | 2 3 40 | 1 4 41 | 2 4 42 | 3 4 43 | 1 5 44 | 1 6 45 | 1 7 46 | 5 7 47 | 6 7 48 | 1 8 49 | 2 8 50 | 3 8 51 | 4 8 52 | 1 9 53 | 3 9 54 | 3 10 55 | 1 11 56 | 5 11 57 | 6 11 58 | 1 12 59 | 1 13 60 | 4 13 61 | 1 14 62 | 2 14 63 | 3 14 64 | 4 14 65 | 6 17 66 | 7 17 67 | 1 18 68 | 2 18 69 | 1 20 70 | 2 20 71 | 1 22 72 | 2 22 73 | 24 26 74 | 25 26 75 | 3 28 76 | 24 28 77 | 25 28 78 | 3 29 79 | 24 30 80 | 27 30 81 | 2 31 82 | 9 31 83 | 1 32 84 | 25 32 85 | 26 32 86 | 29 32 87 | 3 33 88 | 9 33 89 | 15 33 90 | 16 33 91 | 19 33 92 | 21 33 93 | 23 33 94 | 24 33 95 | 30 33 96 | 31 33 97 | 32 33 98 | 9 34 99 | 10 34 100 | 14 34 101 | 15 34 102 | 16 34 103 | 19 34 104 | 20 34 105 | 21 34 106 | 23 34 107 | 24 34 108 | 27 34 109 | 28 34 110 | 29 34 111 | 30 34 112 | 31 34 113 | 32 34 114 | 33 34 115 | -------------------------------------------------------------------------------- /notebooks/plotting-infinities-1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandialabs/toyplot/f71796a34829795deaa65adfa854ddadef0a83d0/notebooks/plotting-infinities-1.pdf -------------------------------------------------------------------------------- /notebooks/plotting-infinities-2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandialabs/toyplot/f71796a34829795deaa65adfa854ddadef0a83d0/notebooks/plotting-infinities-2.pdf -------------------------------------------------------------------------------- /notebooks/plotting-infinities-3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandialabs/toyplot/f71796a34829795deaa65adfa854ddadef0a83d0/notebooks/plotting-infinities-3.pdf -------------------------------------------------------------------------------- /notebooks/plotting-infinities-4.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandialabs/toyplot/f71796a34829795deaa65adfa854ddadef0a83d0/notebooks/plotting-infinities-4.pdf -------------------------------------------------------------------------------- /notebooks/plotting-infinities-data.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandialabs/toyplot/f71796a34829795deaa65adfa854ddadef0a83d0/notebooks/plotting-infinities-data.pdf -------------------------------------------------------------------------------- /notebooks/scatterplot-range-issue.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 17, 6 | "metadata": {}, 7 | "outputs": [ 8 | { 9 | "data": { 10 | "text/plain": [ 11 | "(885, 2)" 12 | ] 13 | }, 14 | "execution_count": 17, 15 | "metadata": {}, 16 | "output_type": "execute_result" 17 | } 18 | ], 19 | "source": [ 20 | "import numpy\n", 21 | "import toyplot\n", 22 | "import toyplot.html\n", 23 | "\n", 24 | "ccc = numpy.load(\"/Users/tshead/Downloads/scatterdata.npy\")\n", 25 | "print(ccc.shape" 26 | ] 27 | }, 28 | { 29 | "cell_type": "code", 30 | "execution_count": 8, 31 | "metadata": {}, 32 | "outputs": [ 33 | { 34 | "data": { 35 | "text/plain": [ 36 | "array([-0.74800959, -0.59287314])" 37 | ] 38 | }, 39 | "execution_count": 8, 40 | "metadata": {}, 41 | "output_type": "execute_result" 42 | } 43 | ], 44 | "source": [ 45 | "ccc.min(axis=0)" 46 | ] 47 | }, 48 | { 49 | "cell_type": "code", 50 | "execution_count": 9, 51 | "metadata": {}, 52 | "outputs": [ 53 | { 54 | "data": { 55 | "text/plain": [ 56 | "array([1. , 0.94738604])" 57 | ] 58 | }, 59 | "execution_count": 9, 60 | "metadata": {}, 61 | "output_type": "execute_result" 62 | } 63 | ], 64 | "source": [ 65 | "ccc.max(axis=0)" 66 | ] 67 | }, 68 | { 69 | "cell_type": "code", 70 | "execution_count": 14, 71 | "metadata": {}, 72 | "outputs": [ 73 | { 74 | "data": { 75 | "text/plain": [ 76 | "'1.15.4'" 77 | ] 78 | }, 79 | "execution_count": 14, 80 | "metadata": {}, 81 | "output_type": "execute_result" 82 | } 83 | ], 84 | "source": [ 85 | "numpy.__version__" 86 | ] 87 | }, 88 | { 89 | "cell_type": "code", 90 | "execution_count": 18, 91 | "metadata": {}, 92 | "outputs": [], 93 | "source": [ 94 | "canvas = toyplot.Canvas(width=400)\n", 95 | "axes = canvas.cartesian()\n", 96 | "mark = axes.scatterplot(ccc[:,0], ccc[:,1], title=\"PCA components\")\n", 97 | "toyplot.html.render(canvas, \"test.html\")" 98 | ] 99 | }, 100 | { 101 | "cell_type": "code", 102 | "execution_count": null, 103 | "metadata": {}, 104 | "outputs": [], 105 | "source": [] 106 | } 107 | ], 108 | "metadata": { 109 | "kernelspec": { 110 | "display_name": "Python 3", 111 | "language": "python", 112 | "name": "python3" 113 | }, 114 | "language_info": { 115 | "codemirror_mode": { 116 | "name": "ipython", 117 | "version": 3 118 | }, 119 | "file_extension": ".py", 120 | "mimetype": "text/x-python", 121 | "name": "python", 122 | "nbconvert_exporter": "python", 123 | "pygments_lexer": "ipython3", 124 | "version": "3.6.7" 125 | } 126 | }, 127 | "nbformat": 4, 128 | "nbformat_minor": 2 129 | } 130 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["flit_core >=3.2,<4"] 3 | build-backend = "flit_core.buildapi" 4 | 5 | [tool.flit.module] 6 | name = "toyplot" 7 | 8 | [project] 9 | classifiers = [ 10 | "Development Status :: 5 - Production/Stable", 11 | "Environment :: Console", 12 | "Environment :: Other Environment", 13 | "Environment :: Web Environment", 14 | "Framework :: IPython", 15 | "Intended Audience :: Science/Research", 16 | "License :: OSI Approved :: BSD License", 17 | "Natural Language :: English", 18 | "Programming Language :: Python :: 3", 19 | "Topic :: Scientific/Engineering :: Visualization", 20 | ] 21 | dependencies = [ 22 | "arrow>=1.0", 23 | "custom_inherit", 24 | "multipledispatch", 25 | "numpy>=1.8.0", 26 | "packaging", 27 | "pypng", 28 | "reportlab", 29 | ] 30 | description = "A modern plotting toolkit supporting electronic publishing and reproducibility." 31 | dynamic = ["version"] 32 | maintainers = [{name="Timothy M. Shead", email="tshead@sandia.gov"}] 33 | name = "toyplot" 34 | requires-python = ">=3.8" 35 | 36 | [project.optional-dependencies] 37 | all = [ 38 | "behave", 39 | "coverage", 40 | "ipykernel", 41 | "nbsphinx", 42 | "pandas", 43 | "scikit-image", 44 | "sphinx >= 3.5", 45 | "sphinx_rtd_theme", 46 | ] 47 | doc = [ 48 | "ipykernel", 49 | "nbsphinx", 50 | "pandas", 51 | "scikit-image", 52 | "sphinx >= 3.5", 53 | "sphinx_rtd_theme", 54 | ] 55 | 56 | [project.scripts] 57 | 58 | [project.urls] 59 | "Chat" = "https://github.com/sandialabs/toyplot/discussions" 60 | "Coverage" = "https://coveralls.io/r/sandialabs/toyplot" 61 | "Documentation" = "https://toyplot.readthedocs.io" 62 | "Issue Tracker" = "https://github.com/sandialabs/toyplot/issues" 63 | "Regression Tests" = "https://github.com/sandialabs/toyplot/actions" 64 | "Source" = "https://github.com/sandialabs/toyplot" 65 | 66 | -------------------------------------------------------------------------------- /regression.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014, Sandia Corporation. Under the terms of Contract 2 | # DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain 3 | # rights in this software. 4 | 5 | import argparse 6 | import subprocess 7 | 8 | parser = argparse.ArgumentParser("Run all Toyplot regression tests.") 9 | parser.add_argument("--show-diff", action="store_true", help="Display differences between failed tests and references.") 10 | arguments = parser.parse_args() 11 | 12 | subprocess.call(["coverage", "run", "--source", "toyplot", "-m", "behave", "--no-logcapture", "-D", "show_diff=True" if arguments.show_diff else "show_diff=False"]) 13 | subprocess.call(["coverage", "report"]) 14 | subprocess.call(["coverage", "html", "--directory", ".cover"]) 15 | -------------------------------------------------------------------------------- /toyplot/broadcast.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014, Sandia Corporation. Under the terms of Contract 2 | # DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain 3 | # rights in this software. 4 | 5 | """Functions for broadcasting values into 1D or 2D arrays. 6 | 7 | The functions in this module are used by Toyplot to handle the conversion from 8 | `constant`, `per-series`, and `per-datum` values into their canonical 1D and 2D 9 | array representations. 10 | """ 11 | 12 | 13 | import numpy 14 | 15 | 16 | def scalar(value, shape): 17 | """Return a 1D or 2D array of floats with the given shape. 18 | 19 | Parameters 20 | ---------- 21 | shape: (tuple) 22 | Shape of the desired output array. A 1-tuple will produce a 1D output 23 | vector containing :math:`N` per-series values. A 2-tuple will produce an :math:`M \\times N` 24 | output matrix of per-datum values grouped into :math:`N` series. 25 | 26 | Returns 27 | ------- 28 | array: :class:`numpy.ndarray` 29 | """ 30 | array = numpy.array(value).astype("float64") 31 | # As a special-case, allow a vector with shape M to be matched-up with an 32 | # M x 1 matrix. 33 | if array.ndim == 1 and isinstance(shape, tuple) and len( 34 | shape) == 2 and array.shape[0] == shape[0] and shape[1] == 1: 35 | return numpy.reshape(array, shape) 36 | return numpy.broadcast_arrays(array, numpy.empty(shape))[0] 37 | 38 | 39 | #def string(value, shape): 40 | # array = numpy.array(value).astype("unicode") 41 | # # As a special-case, allow a vector with shape M to be matched-up with an 42 | # # M x 1 matrix. 43 | # if array.ndim == 1 and isinstance(shape, tuple) and len( 44 | # shape) == 2 and array.shape[0] == shape[0] and shape[1] == 1: 45 | # return numpy.reshape(array, shape) 46 | # return numpy.broadcast_arrays(array, numpy.empty(shape))[0] 47 | 48 | 49 | def pyobject(value, shape): 50 | """Return a 1D or 2D array of objects with the given shape. 51 | 52 | Parameters 53 | ---------- 54 | shape: (tuple) 55 | Shape of the desired output array. A 1-tuple will produce a 1D output 56 | vector containing :math:`N` per-series values. A 2-tuple will produce an :math:`M \\times N` 57 | output matrix of per-datum values grouped into :math:`N` series. 58 | 59 | Returns 60 | ------- 61 | array: :class:`numpy.ndarray` 62 | """ 63 | array = numpy.array(value) 64 | # As a special-case, allow a vector with shape M to be matched-up with an 65 | # M x 1 matrix. 66 | if array.ndim == 1 and isinstance(shape, tuple) and len( 67 | shape) == 2 and array.shape[0] == shape[0] and shape[1] == 1: 68 | return numpy.reshape(array, shape) 69 | result = numpy.empty(shape, dtype="object") 70 | result.flat = [u for u, _ in numpy.broadcast(array, result)] 71 | return result 72 | -------------------------------------------------------------------------------- /toyplot/browser.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014, Sandia Corporation. Under the terms of Contract 2 | # DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain 3 | # rights in this software. 4 | 5 | """Functionality for displaying a Toyplot canvas in a web browser.""" 6 | 7 | 8 | import collections 9 | 10 | def show(canvases, title="Toyplot Figure"): 11 | """Display one or more canvases in a web browser. 12 | 13 | Uses Toyplot's preferred HTML+SVG+Javascript backend to display one-or-more 14 | interactive canvases in a web browser window. 15 | 16 | Because the canvases are displayed in a separate web browser process, this 17 | function returns immediately. 18 | 19 | Parameters 20 | ---------- 21 | canvases: :class:`toyplot.canvas.Canvas` instance or sequence of :class:`toyplot.canvas.Canvas` instances. 22 | The canvases to be displayed. 23 | 24 | title: string, optional 25 | Optional page title to be displayed by the browser. 26 | """ 27 | 28 | import os 29 | import tempfile 30 | import toyplot.canvas 31 | import toyplot.html 32 | import xml.etree.ElementTree as xml 33 | import webbrowser 34 | 35 | if not isinstance(canvases, (toyplot.canvas.Canvas, collections.abc.Iterable)): 36 | raise ValueError("Expected one or more instances of %s, received %s." % (toyplot.canvas.Canvas, type(canvases))) # pragma: no cover 37 | 38 | if isinstance(canvases, toyplot.canvas.Canvas): 39 | canvases = [canvases] 40 | 41 | html = xml.Element("html") 42 | head = xml.SubElement(html, "head") 43 | xml.SubElement(head, "title").text = title 44 | body = xml.SubElement(html, "body") 45 | for canvas in canvases: 46 | body.append(toyplot.html.render(canvas)) 47 | 48 | fd, path = tempfile.mkstemp(suffix=".html") 49 | with os.fdopen(fd, "wb") as stream: 50 | stream.write(xml.tostring(html, method="html")) 51 | webbrowser.open("file://" + path, new=1, autoraise=True) 52 | -------------------------------------------------------------------------------- /toyplot/community-assigned.csv: -------------------------------------------------------------------------------- 1 | 1 4 2 | 2 1 3 | 3 1 4 | 4 1 5 | 5 2 6 | 6 2 7 | 7 2 8 | 8 2 9 | 9 2 10 | 10 2 11 | 11 2 12 | 12 2 13 | -------------------------------------------------------------------------------- /toyplot/community-edges.csv: -------------------------------------------------------------------------------- 1 | 1 2 2 | 1 3 3 | 1 4 4 | 2 3 5 | 2 4 6 | 3 4 7 | 5 6 8 | 5 7 9 | 5 8 10 | 6 7 11 | 6 8 12 | 7 8 13 | 9 10 14 | 9 11 15 | 9 12 16 | 10 11 17 | 10 12 18 | 11 12 19 | 4 5 20 | 8 9 21 | -------------------------------------------------------------------------------- /toyplot/community-truth.csv: -------------------------------------------------------------------------------- 1 | 1 1 2 | 2 1 3 | 3 1 4 | 4 1 5 | 5 2 6 | 6 2 7 | 7 2 8 | 8 2 9 | 9 3 10 | 10 3 11 | 11 3 12 | 12 3 13 | -------------------------------------------------------------------------------- /toyplot/config.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014, Sandia Corporation. Under the terms of Contract 2 | # DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain 3 | # rights in this software. 4 | 5 | """Provides global configuration for Toyplot figures. 6 | 7 | You can write to the attributes in :mod:`toyplot.config` if you wish to change 8 | the default behaviors for multiple figures. 9 | """ 10 | 11 | import os 12 | 13 | autorender = True 14 | """Default value for the :class:`toyplot.canvas.Canvas` autorender feature.""" 15 | 16 | autoformat = os.environ.get("TOYPLOT_AUTOFORMAT", "html") 17 | """Default value for the :class:`toyplot.canvas.Canvas` autoformat feature.""" 18 | 19 | width = None 20 | """Default value for the :class:`toyplot.canvas.Canvas` width.""" 21 | 22 | height = None 23 | """Default value for the :class:`toyplot.canvas.Canvas` height.""" 24 | -------------------------------------------------------------------------------- /toyplot/deliveries.csv: -------------------------------------------------------------------------------- 1 | Date,Delivered,On Time 2 | 15feb2005,553,1.0000 3 | 15mar2005,507,1.0000 4 | 15apr2005,586,1.0000 5 | 15may2005,488,1.0000 6 | 15jun2005,404,1.0000 7 | 15jul2005,306,1.0000 8 | 15aug2005,323,0.9905 9 | 15sep2005,531,0.9959 10 | 15oct2005,677,0.9600 11 | 15nov2005,695,0.9624 12 | 15dec2005,867,0.9229 13 | 15jan2006,557,0.9888 14 | -------------------------------------------------------------------------------- /toyplot/hou.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014, Sandia Corporation. Under the terms of Contract 2 | # DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain 3 | # rights in this software. 4 | 5 | """Functionality for displaying a Toyplot canvas in a Houdini help browser.""" 6 | 7 | 8 | import collections 9 | 10 | def show(canvases, title="Toyplot Figure"): 11 | """Display one or more canvases in a Houdini (https://sidefx.com) help browser. 12 | 13 | Uses Toyplot's preferred HTML+SVG+Javascript backend to display one-or-more 14 | interactive canvases in a floating help browser in Houdini (https://sidefx.com). 15 | 16 | Because the canvases are displayed in a separate web browser process, this 17 | function returns immediately. 18 | 19 | Parameters 20 | ---------- 21 | canvases: :class:`toyplot.canvas.Canvas` instance or sequence of :class:`toyplot.canvas.Canvas` instances. 22 | The canvases to be displayed. 23 | 24 | title: string, optional 25 | Optional page title to be displayed by the browser. 26 | """ 27 | 28 | import os 29 | import tempfile 30 | import xml.etree.ElementTree as xml 31 | 32 | import hou 33 | 34 | import toyplot.canvas 35 | import toyplot.html 36 | 37 | if not isinstance(canvases, (toyplot.canvas.Canvas, collections.abc.Iterable)): 38 | raise ValueError("Expected one or more instances of %s, received %s." % (toyplot.canvas.Canvas, type(canvases))) # pragma: no cover 39 | 40 | if isinstance(canvases, toyplot.canvas.Canvas): 41 | canvases = [canvases] 42 | 43 | html = xml.Element("html") 44 | head = xml.SubElement(html, "head") 45 | xml.SubElement(head, "title").text = title 46 | body = xml.SubElement(html, "body") 47 | for canvas in canvases: 48 | body.append(toyplot.html.render(canvas)) 49 | 50 | fd, path = tempfile.mkstemp(suffix=".html") 51 | with os.fdopen(fd, "wb") as stream: 52 | stream.write(xml.tostring(html, method="html")) 53 | 54 | browser = hou.ui.curDesktop().createFloatingPaneTab(hou.paneTabType.HelpBrowser) 55 | browser.setUrl(f"file://{path}") 56 | 57 | return browser 58 | -------------------------------------------------------------------------------- /toyplot/pdf.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014, Sandia Corporation. Under the terms of Contract 2 | # DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain 3 | # rights in this software. 4 | 5 | """Functions to render PDF documents.""" 6 | 7 | 8 | 9 | import toyplot.require 10 | import toyplot.reportlab.pdf as implementation 11 | 12 | 13 | def render(canvas, fobj=None, width=None, height=None, scale=None): 14 | """Render the PDF representation of a canvas. 15 | 16 | Because the canvas dimensions are specified explicitly at creation time, they 17 | map directly to real-world units in the output PDF image. Use one of 18 | `width`, `height`, or `scale` to override this behavior. 19 | 20 | Parameters 21 | ---------- 22 | canvas: :class:`toyplot.canvas.Canvas` 23 | Canvas to be rendered. 24 | fobj: file-like object, string, or None 25 | The file to write. Use a string filepath to write data directly to disk. 26 | If `None` (the default), the PDF data will be returned to the caller 27 | instead. 28 | width: number, string, or (number, string) tuple, optional 29 | Specify the width of the output image with optional units. If the units 30 | aren't specified, defaults to points. See :ref:`units` for details on 31 | unit conversion in Toyplot. 32 | height: number or (number, string) tuple, optional 33 | Specify the height of the output image with optional units. If the units 34 | aren't specified, defaults to points. See :ref:`units` for details on 35 | unit conversion in Toyplot. 36 | scale: number, optional 37 | Scales the output `canvas` by the given ratio. 38 | 39 | Returns 40 | ------- 41 | pdf: PDF data, or `None` 42 | PDF representation of `canvas`, or `None` if the caller specifies the 43 | `fobj` parameter. 44 | 45 | Examples 46 | -------- 47 | 48 | >>> toyplot.pdf.render(canvas, "figure-1.pdf", width=(4, "inches")) 49 | 50 | Notes 51 | ----- 52 | The output PDF is currently rendered using 53 | :func:`toyplot.reportlab.pdf.render()`. 54 | """ 55 | canvas = toyplot.require.instance(canvas, toyplot.canvas.Canvas) 56 | return implementation.render(canvas, fobj, width, height, scale) 57 | -------------------------------------------------------------------------------- /toyplot/reportlab/pdf.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014, Sandia Corporation. Under the terms of Contract 2 | # DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain 3 | # rights in this software. 4 | 5 | """Functions to render PDF documents using ReportLab.""" 6 | 7 | 8 | 9 | import io 10 | import reportlab.pdfgen.canvas 11 | import toyplot.reportlab 12 | import toyplot.require 13 | import toyplot.svg 14 | 15 | 16 | def render(canvas, fobj=None, width=None, height=None, scale=None): 17 | """Render the PDF representation of a canvas using ReportLab. 18 | 19 | Because the canvas dimensions are specified explicitly at creation time, they 20 | map directly to real-world units in the output PDF image. Use one of 21 | `width`, `height`, or `scale` to override this behavior. 22 | 23 | Parameters 24 | ---------- 25 | canvas: :class:`toyplot.canvas.Canvas` 26 | Canvas to be rendered. 27 | fobj: file-like object or string 28 | The file to write. Use a string filepath to write data directly to disk. 29 | If `None` (the default), the PDF data will be returned to the caller 30 | instead. 31 | width: number, string, or (number, string) tuple, optional 32 | Specify the width of the output image with optional units. If the units 33 | aren't specified, defaults to points. See :ref:`units` for details on 34 | unit conversion in Toyplot. 35 | height: number or (number, string) tuple, optional 36 | Specify the height of the output image with optional units. If the units 37 | aren't specified, defaults to points. See :ref:`units` for details on 38 | unit conversion in Toyplot. 39 | scale: number, optional 40 | Scales the output `canvas` by the given ratio. 41 | 42 | Returns 43 | ------- 44 | pdf: PDF data, or `None` 45 | PDF representation of `canvas`, or `None` if the caller specifies the 46 | `fobj` parameter. 47 | 48 | Examples 49 | -------- 50 | 51 | >>> toyplot.reportlab.pdf.render(canvas, "figure-1.pdf", width=(4, "inches")) 52 | """ 53 | canvas = toyplot.require.instance(canvas, toyplot.canvas.Canvas) 54 | svg = toyplot.svg.render(canvas) 55 | scale = canvas._point_scale(width=width, height=height, scale=scale) 56 | if fobj is None: 57 | stream = io.BytesIO() 58 | surface = reportlab.pdfgen.canvas.Canvas( 59 | stream, pagesize=(scale * canvas.width, scale * canvas.height)) 60 | else: 61 | surface = reportlab.pdfgen.canvas.Canvas( 62 | fobj, pagesize=(scale * canvas.width, scale * canvas.height)) 63 | surface.translate(0, scale * canvas.height) 64 | surface.scale(1, -1) 65 | surface.scale(scale, scale) 66 | toyplot.reportlab.render(svg, surface) 67 | surface.showPage() 68 | surface.save() 69 | if fobj is None: 70 | return stream.getvalue() 71 | -------------------------------------------------------------------------------- /toyplot/svg.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014, Sandia Corporation. Under the terms of Contract 2 | # DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain 3 | # rights in this software. 4 | 5 | """Generates SVG images. 6 | """ 7 | 8 | 9 | import xml.etree.ElementTree as xml 10 | 11 | 12 | import toyplot.html 13 | import toyplot.require 14 | 15 | 16 | def apply_changes(svg, changes): 17 | """Modify the SVG DOM representation of a canvas with the given changes.""" 18 | toyplot.html.apply_changes(svg, changes) 19 | 20 | 21 | def render(canvas, fobj=None, animation=False): 22 | """Render the SVG representation of a canvas. 23 | 24 | Parameters 25 | ---------- 26 | canvas: :class:`toyplot.canvas.Canvas` 27 | The canvas to be rendered. 28 | 29 | fobj: file-like object or string, optional 30 | The file to write. Use a string filepath to write data directly to disk. 31 | If `None` (the default), the SVG tree will be returned to the caller 32 | instead. 33 | 34 | animation: boolean, optional 35 | If `True`, return a representation of the changes to be made to the SVG 36 | tree for animation. 37 | 38 | Returns 39 | ------- 40 | svg: xml.etree.ElementTree.Element or `None` 41 | SVG representation of `canvas`, as a DOM tree, or `None` if the caller 42 | specifies the `fobj` parameter. 43 | 44 | changes: JSON-compatible data structure, or `None` 45 | JSON-compatible representation of the animated changes to `canvas`. 46 | """ 47 | 48 | canvas = toyplot.require.instance(canvas, toyplot.canvas.Canvas) 49 | html, html_animation = toyplot.html.render(canvas, animation=True) 50 | svg = html.find("svg") 51 | 52 | if isinstance(fobj, str): 53 | with open(fobj, "wb") as stream: 54 | stream.write(xml.tostring(svg, method="xml")) 55 | elif fobj is not None: 56 | fobj.write(xml.tostring(svg, method="xml")) 57 | else: 58 | if animation: 59 | return svg, html_animation 60 | else: 61 | return svg 62 | -------------------------------------------------------------------------------- /toyplot/transform.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014, Sandia Corporation. Under the terms of Contract 2 | # DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain 3 | # rights in this software. 4 | 5 | """Functions for manipulating transformation matrices.""" 6 | 7 | 8 | import numpy 9 | 10 | 11 | def rotation(angle): 12 | """Return a 2D transformation matrix. 13 | 14 | Parameters 15 | ---------- 16 | angle: number 17 | Rotation angle in degrees. Positive values produce counterclockwise rotation. 18 | """ 19 | theta = numpy.radians(angle) 20 | cos_theta = numpy.cos(theta) 21 | sin_theta = numpy.sin(theta) 22 | 23 | return numpy.array([[cos_theta, sin_theta], [-sin_theta, cos_theta]]) 24 | --------------------------------------------------------------------------------