From 665c3f2c5d1aeb66fd1af064d09a2f1906052fed Mon Sep 17 00:00:00 2001 From: t-bltg Date: Sat, 18 Jun 2022 12:21:10 +0200 Subject: [PATCH] fix plot size in `png` - rework docs --- README.md | 338 ++++++++++++++++++++---------------- docs/generate_docs.jl | 135 ++++++++++---- src/canvas/braillecanvas.jl | 13 +- src/canvas/dotcanvas.jl | 16 +- src/interface/polarplot.jl | 37 ++-- src/plot.jl | 28 +-- 6 files changed, 339 insertions(+), 228 deletions(-) diff --git a/README.md b/README.md index 374fc709..352df451 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,16 @@ # UnicodePlots -[![License](http://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat)](LICENSE.md) [![PkgEval](https://juliaci.github.io/NanosoldierReports/pkgeval_badges/U/UnicodePlots.named.svg)](https://juliaci.github.io/NanosoldierReports/pkgeval_badges/U/UnicodePlots.html) [![CI](https://github.com/JuliaPlots/UnicodePlots.jl/actions/workflows/ci.yml/badge.svg)](https://github.com/JuliaPlots/UnicodePlots.jl/actions/workflows/ci.yml) [![Coverage Status](https://codecov.io/gh/JuliaPlots/UnicodePlots.jl/branch/master/graphs/badge.svg?branch=master)](https://app.codecov.io/gh/JuliaPlots/UnicodePlots.jl) [![JuliaHub deps](https://juliahub.com/docs/UnicodePlots/deps.svg)](https://juliahub.com/ui/Packages/UnicodePlots/Ctj9q?t=2) [![UnicodePlots Downloads](https://shields.io/endpoint?url=https://pkgs.genieframework.com/api/v1/badge/UnicodePlots)](https://pkgs.genieframework.com?packages=UnicodePlots) +[![License](http://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat)](LICENSE.md) +[![PkgEval](https://juliaci.github.io/NanosoldierReports/pkgeval_badges/U/UnicodePlots.named.svg)](https://juliaci.github.io/NanosoldierReports/pkgeval_badges/U/UnicodePlots.html) +[![CI](https://github.com/JuliaPlots/UnicodePlots.jl/actions/workflows/ci.yml/badge.svg)](https://github.com/JuliaPlots/UnicodePlots.jl/actions/workflows/ci.yml) +[![Coverage Status](https://codecov.io/gh/JuliaPlots/UnicodePlots.jl/branch/master/graphs/badge.svg?branch=master)](https://app.codecov.io/gh/JuliaPlots/UnicodePlots.jl) +[![JuliaHub deps](https://juliahub.com/docs/UnicodePlots/deps.svg)](https://juliahub.com/ui/Packages/UnicodePlots/Ctj9q?t=2) +[![UnicodePlots Downloads](https://shields.io/endpoint?url=https://pkgs.genieframework.com/api/v1/badge/UnicodePlots)](https://pkgs.genieframework.com?packages=UnicodePlots) Advanced [`Unicode`](https://en.wikipedia.org/wiki/Unicode) plotting library designed for use in `Julia`'s `REPL`. -Physical quantities of [`Unitful.jl`](https://github.com/PainterQubits/Unitful.jl) are supported on a subset of plotting methods. +![Banner](https://github.com/JuliaPlots/UnicodePlots.jl/raw/unicodeplots-docs/2.10/banner.png) ## High-level Interface @@ -13,25 +18,26 @@ There are a couple of ways to generate typical plots without much verbosity. Here is a list of the main high-level functions for common scenarios: - * [`scatterplot`](https://github.com/JuliaPlots/UnicodePlots.jl#scatterplot) (Scatter Plot) - * [`lineplot`](https://github.com/JuliaPlots/UnicodePlots.jl#lineplot) (Line Plot) - * [`stairs`](https://github.com/JuliaPlots/UnicodePlots.jl#staircase-plot) (Staircase Plot) - * [`barplot`](https://github.com/JuliaPlots/UnicodePlots.jl#barplot) (Bar Plot - horizontal) - * [`histogram`](https://github.com/JuliaPlots/UnicodePlots.jl#histogram) (Histogram - horizontal / vertical) - * [`boxplot`](https://github.com/JuliaPlots/UnicodePlots.jl#boxplot) (Box Plot - horizontal) - * [`spy`](https://github.com/JuliaPlots/UnicodePlots.jl#sparsity-pattern) (Sparsity Pattern) - * [`densityplot`](https://github.com/JuliaPlots/UnicodePlots.jl#density-plot) (Density Plot) - * [`contourplot`](https://github.com/JuliaPlots/UnicodePlots.jl#contour-plot) (Contour Plot) - * [`polarplot`](https://github.com/JuliaPlots/UnicodePlots.jl#polar-plot) (Polar Plot) - * [`heatmap`](https://github.com/JuliaPlots/UnicodePlots.jl#heatmap-plot) (Heatmap Plot) - * [`surfaceplot`](https://github.com/JuliaPlots/UnicodePlots.jl#surface-plot) (Surface Plot - 3D) - * [`isosurface`](https://github.com/JuliaPlots/UnicodePlots.jl#isosurface-plot) (Isosurface Plot - 3D) - -
Introduction - -Here is a quick hello world example of a typical use-case: - -```julia + - [`scatterplot`](https://github.com/JuliaPlots/UnicodePlots.jl#scatterplot) (Scatter Plot) + - [`lineplot`](https://github.com/JuliaPlots/UnicodePlots.jl#lineplot) (Line Plot) + - [`stairs`](https://github.com/JuliaPlots/UnicodePlots.jl#staircase-plot) (Staircase Plot) + - [`barplot`](https://github.com/JuliaPlots/UnicodePlots.jl#barplot) (Bar Plot - horizontal) + - [`histogram`](https://github.com/JuliaPlots/UnicodePlots.jl#histogram) (Histogram - horizontal / vertical) + - [`boxplot`](https://github.com/JuliaPlots/UnicodePlots.jl#boxplot) (Box Plot - horizontal) + - [`spy`](https://github.com/JuliaPlots/UnicodePlots.jl#sparsity-pattern) (Sparsity Pattern) + - [`densityplot`](https://github.com/JuliaPlots/UnicodePlots.jl#density-plot) (Density Plot) + - [`contourplot`](https://github.com/JuliaPlots/UnicodePlots.jl#contour-plot) (Contour Plot) + - [`polarplot`](https://github.com/JuliaPlots/UnicodePlots.jl#polar-plot) (Polar Plot) + - [`heatmap`](https://github.com/JuliaPlots/UnicodePlots.jl#heatmap-plot) (Heatmap Plot) + - [`surfaceplot`](https://github.com/JuliaPlots/UnicodePlots.jl#surface-plot) (Surface Plot - 3D) + - [`isosurface`](https://github.com/JuliaPlots/UnicodePlots.jl#isosurface-plot) (Isosurface Plot - 3D) + +
+ Introduction + + Here is a quick hello world example of a typical use-case: + + ```julia using UnicodePlots plt = lineplot([-1, 2, 3, 7], [-1, 2, 9, 4], title="Example Plot", name="my line", xlabel="x", ylabel="y") @@ -39,11 +45,11 @@ plt = lineplot([-1, 2, 3, 7], [-1, 2, 9, 4], ![Basic Canvas](https://github.com/JuliaPlots/UnicodePlots.jl/raw/unicodeplots-docs/2.10/lineplot1.png) -There are other types of `Canvas` available (see section [Low-level Interface](https://github.com/JuliaPlots/UnicodePlots.jl#low-level-interface)). + There are other types of `Canvas` available (see section [Low-level Interface](https://github.com/JuliaPlots/UnicodePlots.jl#low-level-interface)). -In some situations, such as printing to a file, using `AsciiCanvas`, `DotCanvas` or `BlockCanvas` might lead to better results: + In some situations, such as printing to a file, using `AsciiCanvas`, `DotCanvas` or `BlockCanvas` might lead to better results: -```julia + ```julia lineplot([-1, 2, 3, 7], [-1, 2, 9, 4], title="Example Plot", name="my line", xlabel="x", ylabel="y", canvas=DotCanvas, border=:ascii) @@ -51,97 +57,109 @@ lineplot([-1, 2, 3, 7], [-1, 2, 9, 4], ![Basic Canvas](https://github.com/JuliaPlots/UnicodePlots.jl/raw/unicodeplots-docs/2.10/lineplot2.png) -Some plot methods have a mutating variant that ends with a exclamation mark: + Some plot methods have a mutating variant that ends with a exclamation mark: -```julia + ```julia lineplot!(plt, [0, 4, 8], [10, 1, 10], color=:blue, name="other line") ``` ![Basic Canvas](https://github.com/JuliaPlots/UnicodePlots.jl/raw/unicodeplots-docs/2.10/lineplot3.png) -
-
Scatterplot -```julia + Physical quantities of [`Unitful.jl`](https://github.com/PainterQubits/Unitful.jl) are supported on a subset of plotting methods. + +
+ +
+ Scatterplot + + ```julia scatterplot(randn(50), randn(50), title="My Scatterplot") ``` ![Scatterplot](https://github.com/JuliaPlots/UnicodePlots.jl/raw/unicodeplots-docs/2.10/scatterplot1.png) -Axis scaling (`xscale` and/or `yscale`) is supported: choose from (`:identity`, `:ln`, `:log2`, `:log10`) or use an arbitrary scale function: + Axis scaling (`xscale` and/or `yscale`) is supported: choose from (`:identity`, `:ln`, `:log2`, `:log10`) or use an arbitrary scale function: -```julia + ```julia scatterplot(1:10, 1:10, xscale=:log10, yscale=:ln) ``` ![Scatterplot](https://github.com/JuliaPlots/UnicodePlots.jl/raw/unicodeplots-docs/2.10/scatterplot2.png) -For the axis scale exponent, one can revert to using `ASCII` characters instead of `Unicode` ones using the keyword `unicode_exponent=false`: + For the axis scale exponent, one can revert to using `ASCII` characters instead of `Unicode` ones using the keyword `unicode_exponent=false`: -```julia + ```julia scatterplot(1:10, 1:10, xscale=:log10, yscale=:ln, unicode_exponent=false) ``` ![Scatterplot](https://github.com/JuliaPlots/UnicodePlots.jl/raw/unicodeplots-docs/2.10/scatterplot3.png) -Using a `marker` is supported, choose a `Char`, a unit length `String` or a symbol name such as `:circle` (more from `keys(UnicodePlots.MARKERS)`). One can also provide a vector of `marker`s and/or `color`s as in the following example: + Using a `marker` is supported, choose a `Char`, a unit length `String` or a symbol name such as `:circle` (more from `keys(UnicodePlots.MARKERS)`). + One can also provide a vector of `marker`s and/or `color`s as in the following example: -```julia + ```julia scatterplot([1, 2, 3], [3, 4, 1], marker=[:circle, '', "∫"], color=[:red, nothing, :yellow]) ``` ![Scatterplot](https://github.com/JuliaPlots/UnicodePlots.jl/raw/unicodeplots-docs/2.10/scatterplot4.png) -As with `lineplot`, `scatterplot` supports plotting physical `Unitful` quantities.
+ As with `lineplot`, `scatterplot` supports plotting physical `Unitful` quantities. +
-
Lineplot +
+ Lineplot -```julia + ```julia lineplot([1, 2, 7], [9, -6, 8], title="My Lineplot") ``` ![Lineplot](https://github.com/JuliaPlots/UnicodePlots.jl/raw/unicodeplots-docs/2.10/lineplot4.png) -It's also possible to specify a function and a range: + It's also possible to specify a function and a range: -```julia + ```julia plt = lineplot([cos, sin], -π/2, 2π) ``` ![Lineplot](https://github.com/JuliaPlots/UnicodePlots.jl/raw/unicodeplots-docs/2.10/lineplot5.png) -You can also plot lines by specifying an intercept and slope: + You can also plot lines by specifying an intercept and slope: -```julia + ```julia lineplot!(plt, -.5, .2, name="line") ``` ![Lineplot](https://github.com/JuliaPlots/UnicodePlots.jl/raw/unicodeplots-docs/2.10/lineplot6.png) -Physical units are supported through `Unitful`: + Physical units are supported through `Unitful`: -```julia + ```julia using Unitful a = 1u"m/s^2" t = (0:100) * u"s" lineplot(a / 2 * t .^ 2, a * t, xlabel = "position", ylabel = "speed") ``` ![Lineplot](https://github.com/JuliaPlots/UnicodePlots.jl/raw/unicodeplots-docs/2.10/lineplot7.png) -
-
Staircase plot +
-```julia +
+ Staircase plot + + ```julia # supported style are :pre and :post stairs([1, 2, 4, 7, 8], [1, 3, 4, 2, 7], color=:red, style=:post, title="My Staircase Plot") ``` ![Staircase](https://github.com/JuliaPlots/UnicodePlots.jl/raw/unicodeplots-docs/2.10/stairs1.png) -
-
Barplot +
-```julia +
+ Barplot + + ```julia barplot(["Paris", "New York", "Moskau", "Madrid"], [2.244, 8.406, 11.92, 3.165], title="Population") @@ -149,112 +167,126 @@ barplot(["Paris", "New York", "Moskau", "Madrid"], ![Barplot](https://github.com/JuliaPlots/UnicodePlots.jl/raw/unicodeplots-docs/2.10/barplot1.png) -*Note*: You can use the keyword argument `symbols` to specify the characters that should be used to plot the bars (e.g. `symbols=['#']`).
+ _Note_: You can use the keyword argument `symbols` to specify the characters that should be used to plot the bars (e.g. `symbols=['#']`). +
-
Histogram +
+ Histogram -```julia + ```julia histogram(randn(1_000) .* .1, nbins=15, closed=:left) ``` ![Histogram](https://github.com/JuliaPlots/UnicodePlots.jl/raw/unicodeplots-docs/2.10/histogram1.png) -The `histogram` function also supports axis scaling using the parameter `xscale`: + The `histogram` function also supports axis scaling using the parameter `xscale`: -```julia + ```julia histogram(randn(1_000) .* .1, nbins=15, closed=:right, xscale=:log10) ``` ![Histogram](https://github.com/JuliaPlots/UnicodePlots.jl/raw/unicodeplots-docs/2.10/histogram2.png) -Vertical histograms are supported: + Vertical histograms are supported: -```julia + ```julia histogram(randn(1_000_000) .* .1, nbins=100, vertical=true) ``` ![Histogram](https://github.com/JuliaPlots/UnicodePlots.jl/raw/unicodeplots-docs/2.10/histogram3.png) -
-
Boxplot +
-```julia +
+ Boxplot + + ```julia boxplot([1, 3, 3, 4, 6, 10]) ``` ![Boxplot](https://github.com/JuliaPlots/UnicodePlots.jl/raw/unicodeplots-docs/2.10/boxplot1.png) -```julia + ```julia boxplot(["one", "two"], [[1, 2, 3, 4, 5], [2, 3, 4, 5, 6, 7, 8, 9]], title="Grouped Boxplot", xlabel="x") ``` ![Boxplot](https://github.com/JuliaPlots/UnicodePlots.jl/raw/unicodeplots-docs/2.10/boxplot2.png) -
-
Sparsity Pattern +
-```julia +
+ Sparsity Pattern + + ```julia using SparseArrays spy(sprandn(50, 120, .05)) ``` ![Spy](https://github.com/JuliaPlots/UnicodePlots.jl/raw/unicodeplots-docs/2.10/spy1.png) -Plotting the zeros pattern is also possible using `show_zeros=true`: + Plotting the zeros pattern is also possible using `show_zeros=true`: -```julia + ```julia using SparseArrays spy(sprandn(50, 120, .9), show_zeros=true) ``` ![Spy](https://github.com/JuliaPlots/UnicodePlots.jl/raw/unicodeplots-docs/2.10/spy2.png) -
-
Density Plot +
+ +
+ Density Plot -```julia + ```julia plt = densityplot(randn(1_000), randn(1_000)) densityplot!(plt, randn(1_000) .+ 2, randn(1_000) .+ 2) ``` ![Densityplot](https://github.com/JuliaPlots/UnicodePlots.jl/raw/unicodeplots-docs/2.10/densityplot1.png) -
-
Contour Plot +
-```julia +
+ Contour Plot + + ```julia contourplot(-3:.01:3, -7:.01:3, (x, y) -> exp(-(x / 2)^2 - ((y + 2) / 4)^2)) ``` ![Contourplot](https://github.com/JuliaPlots/UnicodePlots.jl/raw/unicodeplots-docs/2.10/contourplot1.png) -The keyword `levels` controls the number of contour levels. One can also choose a `colormap` as with `heatmap`, and disable the colorbar using `colorbar=false`.
+ The keyword `levels` controls the number of contour levels. One can also choose a `colormap` as with `heatmap`, and disable the colorbar using `colorbar=false`. +
-
Heatmap Plot +
+ Heatmap Plot -```julia + ```julia heatmap(repeat(collect(0:10)', outer=(11, 1)), zlabel="z") ``` ![Heatmap](https://github.com/JuliaPlots/UnicodePlots.jl/raw/unicodeplots-docs/2.10/heatmap1.png) -The `heatmap` function also supports axis scaling using the parameters `xfact`, `yfact` and axis offsets after scaling using `xoffset` and `yoffset`. + The `heatmap` function also supports axis scaling using the parameters `xfact`, `yfact` and axis offsets after scaling using `xoffset` and `yoffset`. -The `colormap` parameter may be used to specify a named or custom colormap. See the `heatmap` function documentation for more details. + The `colormap` parameter may be used to specify a named or custom colormap. See the `heatmap` function documentation for more details. -In addition, the `colorbar` and `colorbar_border` options may be used to toggle the colorbar and configure its border. + In addition, the `colorbar` and `colorbar_border` options may be used to toggle the colorbar and configure its border. -The `zlabel` option and `zlabel!` method may be used to set the `z` axis (colorbar) label. + The `zlabel` option and `zlabel!` method may be used to set the `z` axis (colorbar) label. -```julia + ```julia heatmap(collect(0:30) * collect(0:30)', xfact=.1, yfact=.1, xoffset=-1.5, colormap=:inferno) ``` ![Heatmap](https://github.com/JuliaPlots/UnicodePlots.jl/raw/unicodeplots-docs/2.10/heatmap2.png) -
-
Polar Plot +
-Plots data in polar coordinates with `θ` the angles in radians. +
+ Polar Plot -```julia + Plots data in polar coordinates with `θ` the angles in radians. + + ```julia polarplot(range(0, 2π, length = 20), range(0, 2, length = 20)) ``` ![Polarplot](https://github.com/JuliaPlots/UnicodePlots.jl/raw/unicodeplots-docs/2.10/polarplot1.png) @@ -262,117 +294,121 @@ polarplot(range(0, 2π, length = 20), range(0, 2, length = 20))
-
Surface Plot +
+ Surface Plot -Plots a colored surface using height values `z` above a `x-y` plane, in three dimensions (masking values using `NaN`s is supported). + Plots a colored surface using height values `z` above a `x-y` plane, in three dimensions (masking values using `NaN`s is supported). -```julia + ```julia sombrero(x, y) = 15sinc(√(x^2 + y^2) / π) surfaceplot(-8:.5:8, -8:.5:8, sombrero, colormap=:jet) ``` ![Surfaceplot](https://github.com/JuliaPlots/UnicodePlots.jl/raw/unicodeplots-docs/2.10/surfaceplot1.png) -Use `lines=true` to increase the density (underlying call to `lineplot` instead of `scatterplot`, with color interpolation). To plot a slice in 3D, use an anonymous function which maps to a constant value: `zscale=z -> a_constant`: + Use `lines=true` to increase the density (underlying call to `lineplot` instead of `scatterplot`, with color interpolation). + To plot a slice in 3D, use an anonymous function which maps to a constant value: `zscale=z -> a_constant`: -```julia + ```julia surfaceplot( -2:2, -2:2, (x, y) -> 15sinc(√(x^2 + y^2) / π), zscale=z -> 0, lines=true, colormap=:jet ) ``` ![Surfaceplot](https://github.com/JuliaPlots/UnicodePlots.jl/raw/unicodeplots-docs/2.10/surfaceplot2.png) -
-
Isosurface Plot +
-Uses [`MarchingCubes.jl`](https://github.com/JuliaGeometry/MarchingCubes.jl) to extract an isosurface, where `isovalue` controls the surface isovalue. Using `centroid` enables plotting the triangulation centroids instead of the triangle vertices (better for small plots). Back face culling (hide not visible facets) can be activated using `cull=true`. One can use the legacy 'Marching Cubes' algorithm using `legacy=true`. +
+ Isosurface Plot -```julia + Uses [`MarchingCubes.jl`](https://github.com/JuliaGeometry/MarchingCubes.jl) to extract an isosurface, where `isovalue` controls the surface isovalue. + Using `centroid` enables plotting the triangulation centroids instead of the triangle vertices (better for small plots). + Back face culling (hide not visible facets) can be activated using `cull=true`. + One can use the legacy 'Marching Cubes' algorithm using `legacy=true`. + + ```julia torus(x, y, z, r=0.2, R=0.5) = (√(x^2 + y^2) - R)^2 + z^2 - r^2 isosurface(-1:.1:1, -1:.1:1, -1:.1:1, torus, cull=true, zoom=2, elevation=50) ``` ![Isosurface](https://github.com/JuliaPlots/UnicodePlots.jl/raw/unicodeplots-docs/2.10/isosurface.png) -
+ +
## Documentation -
Installation +
+ Installation -To install UnicodePlots, start up `Julia` and type the following code snippet into the `REPL` (makes use of the native `Julia` package manager `Pkg`): + To install UnicodePlots, start up `Julia` and type the following code snippet into the `REPL` (makes use of the native `Julia` package manager `Pkg`): ```julia julia> using Pkg julia> Pkg.add("UnicodePlots") ``` -
- -
Saving figures -Saving plots as `png` or `txt` files using the `savefig` command is supported (saving as `png` is experimental and resulting images might slightly change without warnings). - -To recover the plot as a string with ansi color codes use `string(p; color=true)`.
- -
Color mode +
-When the `COLORTERM` environment variable is set to either `24bit` or `truecolor`, `UnicodePlots` will use [24bit colors](https://en.wikipedia.org/wiki/ANSI_escape_code#24-bit) as opposed to [8bit colors](https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit) or even [4bit colors](https://en.wikipedia.org/wiki/ANSI_escape_code#3-bit_and_4-bit) for named colors. +
+ Saving figures -One can force a specific colormode using either `UnicodePlots.truecolors!()` or `UnicodePlots.colors256!()`. + Saving plots as `png` or `txt` files using the `savefig` command is supported (saving as `png` is experimental and resulting images might slightly change without warnings). -Named colors such as `:red` or `:light_red` will use `256` color values (rendering will be terminal dependent). In order to force named colors to use true colors instead, use `UnicodePlots.USE_LUT[]=true`. + To recover the plot as a string with ansi color codes use `string(p; color=true)`. +
-The default color cycle can be changed to bright (high intensity) colors using `UnicodePlots.brightcolors!()` instead of the default `UnicodePlots.faintcolors!()`.
+
+ Color mode -
3D plots + When the `COLORTERM` environment variable is set to either `24bit` or `truecolor`, `UnicodePlots` will use [24bit colors](https://en.wikipedia.org/wiki/ANSI_escape_code#24-bit) as opposed to [8bit colors](https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit) or even [4bit colors](https://en.wikipedia.org/wiki/ANSI_escape_code#3-bit_and_4-bit) for named colors. -3d plots use a so-called "Model-View-Projection" transformation matrix `MVP` on input data to project 3D plots to a 2D screen. + One can force a specific colormode using either `UnicodePlots.truecolors!()` or `UnicodePlots.colors256!()`. -Use keywords`elevation`, `azimuth`, `up` or `zoom` to control the "View" matrix, a.k.a., camera. + Named colors such as `:red` or `:light_red` will use `256` color values (rendering will be terminal dependent). In order to force named colors to use true colors instead, use `UnicodePlots.USE_LUT[]=true`. -The `projection` type for `MVP` can be set to either `:perspective` or `:orthographic`. + The default color cycle can be changed to bright (high intensity) colors using `UnicodePlots.brightcolors!()` instead of the default `UnicodePlots.faintcolors!()`. +
-Displaying the `x`, `y`, and `z` axes can be controlled using the `axes3d` keyword. +
+ 3D plots -For enhanced resolution, use a wider and/or taller `Plot` (this can be achieved using `default_size!(width=60)` for all future plots).
+ 3d plots use a so-called "Model-View-Projection" transformation matrix `MVP` on input data to project 3D plots to a 2D screen. -
Layout + Use keywords`elevation`, `azimuth`, `up` or `zoom` to control the "View" matrix, a.k.a., camera. -`UnicodePlots` is integrated in [`Plots`](https://github.com/JuliaPlots/Plots.jl) as a backend, with support for [basic layout](https://docs.juliaplots.org/stable/gallery/unicodeplots/generated/unicodeplots-ref17). + The `projection` type for `MVP` can be set to either `:perspective` or `:orthographic`. -For a more complex layout, use [`Term`](https://github.com/FedeClaudi/Term.jl): + Displaying the `x`, `y`, and `z` axes can be controlled using the `axes3d` keyword. -```julia -using UnicodePlots, Term + For enhanced resolution, use a wider and/or taller `Plot` (this can be achieved using `default_size!(width=60)` for all future plots). +
-panel(plot; kw...) = Panel(string(plot, color=true); fit=true, kw...) +
+ Layout -print( - panel(lineplot([cos, sin], -π/2, 2π); title="lineplot", style="yellow") * - panel(contourplot(-3:.01:3, -7:.01:3, (x, y) -> exp(-(x / 2)^2 - ((y + 2) / 4)^2)); title="contourplot", style="red") * - panel(surfaceplot(-8:.5:8, -8:.5:8, (x, y) -> 15sinc(√(x^2 + y^2) / π)); title="surfaceplot", style="blue") / ( - panel(histogram(randn(1_000_000), nbins=100, vertical=true); title="histogram", style="green") * - panel(densityplot(randn(1_000), randn(1_000)); title="densityplot", style="cyan") - ) -) -``` + `UnicodePlots` is integrated in [`Plots`](https://github.com/JuliaPlots/Plots.jl) as a backend, with support for [basic layout](https://docs.juliaplots.org/stable/gallery/unicodeplots/generated/unicodeplots-ref17). + For a more complex layout, use the [`grid`](https://fedeclaudi.github.io/Term.jl/dev/layout/grid) function from [`Term`](https://github.com/FedeClaudi/Term.jl).
-
Know Issues +
+ Know Issues -Using a non `true monospace font` can lead to visual problems on a `BrailleCanvas` (border versus canvas). + Using a non `true monospace font` can lead to visual problems on a `BrailleCanvas` (border versus canvas). -Either change the font to e.g. [JuliaMono](https://juliamono.netlify.app/) or use `border=:dotted` keyword argument in the plots. + Either change the font to e.g. [JuliaMono](https://juliamono.netlify.app/) or use `border=:dotted` keyword argument in the plots. -For a `Jupyter` notebook with the `IJulia` kernel see [here](https://juliamono.netlify.app/faq/#can_i_use_this_font_in_a_jupyter_notebook_and_how_do_i_do_it). + For a `Jupyter` notebook with the `IJulia` kernel see [here](https://juliamono.netlify.app/faq/#can_i_use_this_font_in_a_jupyter_notebook_and_how_do_i_do_it). -(Experimental) Terminals seem to respect a standard aspect ratio of `4:3`, hence a square matrix does not often look square in the terminal. + (Experimental) Terminals seem to respect a standard aspect ratio of `4:3`, hence a square matrix does not often look square in the terminal. -You can pass the experimental keyword `fix_ar=true` to `spy` or `heatmap` in order to recover a unit aspect ratio.
+ You can pass the experimental keyword `fix_ar=true` to `spy` or `heatmap` in order to recover a unit aspect ratio. +
-
Methods (API) +
+ Methods (API) - - `title!(plot::Plot, title::String)` + - `title!(plot::Plot, title::String)` - `title` the string to write in the top center of the plot window. If the title is empty the whole line of the title will not be drawn @@ -418,11 +454,13 @@ The method `label!` is responsible for the setting all the textual decorations o - `annotate!(plot::Plot, x::Number, y::Number, text::AbstractString; kw...)` - `text` arbitrary annotation at position (x, y) -
-
Keywords description (API) +
+ +
+ Keywords description (API) -All plots support the set (or a subset) of the following named parameters: + All plots support the set (or a subset) of the following named parameters: - `symbols::Array = ['■']`: characters used to render the bars. - `title::String = ""`: text displayed on top of the plot. @@ -506,11 +544,13 @@ All plots support the set (or a subset) of the following named parameters: _Note_: If you want to print the plot into a file but have monospace issues with your font, you should probably try setting `border=:ascii` and `canvas=AsciiCanvas` (or `canvas=DotCanvas` for scatterplots). -
-
Low-level Interface +
-The primary structures that do all the heavy lifting behind the curtain are subtypes of `Canvas`. A canvas is a graphics object for rasterized plotting. Basically, it uses Unicode characters to represent pixel. +
+ Low-level Interface + + The primary structures that do all the heavy lifting behind the curtain are subtypes of `Canvas`. A canvas is a graphics object for rasterized plotting. Basically, it uses Unicode characters to represent pixel. Here is a simple example: @@ -560,11 +600,13 @@ The following types of `Canvas` are implemented: - **BarplotGraphics**: This graphics area is special in that it does not support any pixel manipulation. It is essentially the barplot without decorations but the numbers. It does only support one method `addrow!` which allows the user to add additional bars to the graphics object. -
-
Documentation update +
-The following snippet: +
+ Documentation update + + The following snippet: ```bash $ cd docs $ julia generate_docs.jl @@ -572,7 +614,8 @@ $ (cd imgs; julia gen_imgs.jl) ``` will regenerate `README.md` and the example images with root (prefix) url https://github.com/JuliaPlots/UnicodePlots.jl/raw/unicodeplots-docs. -
+ +
## License @@ -581,3 +624,4 @@ This code is free to use under the terms of the MIT license. ## Acknowledgement Inspired by [TextPlots.jl](https://github.com/sunetos/TextPlots.jl), which in turn was inspired by [Drawille](https://github.com/asciimoo/drawille). + diff --git a/docs/generate_docs.jl b/docs/generate_docs.jl index bbbe4c11..517ba361 100644 --- a/docs/generate_docs.jl +++ b/docs/generate_docs.jl @@ -1,8 +1,10 @@ using UnicodePlots using Markdown +using Term import Markdown: MD, Paragraph, plain main() = begin + warn = "WARNING: this file has been automatically generated, please update UnicodePlots/docs/generate_docs.jl instead" docs_url = "https://github.com/JuliaPlots/UnicodePlots.jl/raw/unicodeplots-docs" ver = "2.10" @@ -243,7 +245,7 @@ main() = begin will regenerate `README.md` and the example images with root (prefix) url $(docs_url). """) - readme = plain(md""" + readme = plain_md_par(""" # UnicodePlots [![License](http://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat)](LICENSE.md) @@ -255,7 +257,7 @@ main() = begin Advanced [`Unicode`](https://en.wikipedia.org/wiki/Unicode) plotting library designed for use in `Julia`'s `REPL`. -Physical quantities of [`Unitful.jl`](https://github.com/PainterQubits/Unitful.jl) are supported on a subset of plotting methods. +![Banner]($docs_url/$ver/banner.png) ## High-level Interface @@ -293,6 +295,9 @@ Here is a list of the main high-level functions for common scenarios: Some plot methods have a mutating variant that ends with a exclamation mark: $(examples.lineplot3) + + Physical quantities of [`Unitful.jl`](https://github.com/PainterQubits/Unitful.jl) are supported on a subset of plotting methods. +
@@ -490,23 +495,7 @@ Here is a list of the main high-level functions for common scenarios: `UnicodePlots` is integrated in [`Plots`](https://github.com/JuliaPlots/Plots.jl) as a backend, with support for [basic layout](https://docs.juliaplots.org/stable/gallery/unicodeplots/generated/unicodeplots-ref17). - For a more complex layout, use [`Term`](https://github.com/FedeClaudi/Term.jl): - -```julia -using UnicodePlots, Term - -panel(plot; kw...) = Panel(string(plot, color=true); fit=true, kw...) - -print( - panel(lineplot([cos, sin], -π/2, 2π); title="lineplot", style="yellow") * - panel(contourplot(-3:.01:3, -7:.01:3, (x, y) -> exp(-(x / 2)^2 - ((y + 2) / 4)^2)); title="contourplot", style="red") * - panel(surfaceplot(-8:.5:8, -8:.5:8, (x, y) -> 15sinc(√(x^2 + y^2) / π)); title="surfaceplot", style="blue") / ( - panel(histogram(randn(1_000_000), nbins=100, vertical=true); title="histogram", style="green") * - panel(densityplot(randn(1_000), randn(1_000)); title="densityplot", style="cyan") - ) -) -``` - + For a more complex layout, use the [`grid`](https://fedeclaudi.github.io/Term.jl/dev/layout/grid) function from [`Term`](https://github.com/FedeClaudi/Term.jl).
@@ -557,47 +546,123 @@ Inspired by [TextPlots.jl](https://github.com/sunetos/TextPlots.jl), which in tu """) mkpath("imgs/$ver") + open("imgs/gen_imgs.jl", "w") do io println(io, """ - # WARNING: this file has been automatically generated, please update UnicodePlots/docs/generate_docs.jl instead - using UnicodePlots, StableRNGs, SparseArrays, Unitful + # $warn + using UnicodePlots, StableRNGs, SparseArrays, Unitful, Term # UnicodePlots.brightcolors!() include(joinpath(dirname(pathof(UnicodePlots)), "..", "test", "fixes.jl")) + cursor_hide(io::IO) = print(io, "\x1b[?25l") + cursor_show(io::IO) = print(io, "\x1b[?25h") + + banner() = begin + default_size!(height=10) + + panel(plt; kw...) = Panel(string(plt, color=true); fit=true, kw...) + + panels = ( + line = panel(lineplot(t -> exp(-.15t) * sinpi(.5t), xlabel="t", ylabel="y(t)", name = "decay"); title="lineplot", style="orange1"), + scat = panel(scatterplot(1:6, 1:6, xscale=:log10, yscale=:ln); title="scatterplot", style="yellow1"), + cont = panel(contourplot(-3:.01:3, -7:.01:3, (x, y) -> exp(-(x / 2)^2 - ((y + 2) / 4)^2)); title="contourplot", style="red1"), + surf = panel(surfaceplot(-8:.5:8, -8:.5:8, (x, y) -> 15sinc(√(x^2 + y^2) / π)); title="surfaceplot", style="royal_blue1"), + iso = panel(isosurface(-1:.1:1, -1:.1:1, -1:.1:1, (x, y, z) -> (√(x^2 + y^2) - 0.5)^2 + z^2 - 0.2^2, cull=true, zoom=2, elevation=50); title="isosurface", style="cornsilk1"), + vhist = panel(histogram(randn(1_000_000), nbins=60, vertical=true); title="vertical histogram", style="green1"), + hhist = panel(histogram(randn(1_000) .* 0.1, nbins=15); title="horizontal histogram", style="dodger_blue2"), + dens = panel(densityplot(randn(1_000), randn(1_000)); title="densityplot", style="cyan1"), + hmap = panel(heatmap(collect(0:20) * collect(0:20)', xfact=.1, yfact=.1); title="heatmap", style="magenta1"), + bar = panel(barplot(["Paris", "New York", "Madrid"], [2.244, 8.406, 3.165]); title="barplot", style="gold1"), + polar = panel(polarplot(range(0, 2π, length = 20), range(0, 2, length = 20)); title="polarplot", style="chartreuse1"), + box = panel(boxplot(["one", "two"], [collect(1:5), collect(4:9)]); title="boxplot", style="grey11"), + stair = panel(stairs([1, 2, 4, 7, 8], [1, 3, 4, 2, 2]); title="stair", style="aquamarine1"), + spy = panel(spy([1 -1 0; -1 2 1; 0 -1 1]); title="spy", style="salmon1"), + ) + g = grid(panels, layout=:((line * scat * polar * stair) / (dens * cont * surf * iso) / (hhist * vhist * (bar / (box * spy))))) + + if true + cursor_hide(stdout) + run(`clear`) + print(stdout, g) + win = if "WINDOWID" in keys(ENV) + ENV["WINDOWID"] + else + readchomp(`xdotool getactivewindow`) + end + run(`import -window \$win $ver/banner.png`) + cursor_show(stdout) + else + print(stdout, g) + open("$ver/banner.txt", "w") do io + print(io, g) + end + end + end + main() = begin - rng = StableRNG(1337) + rng = StableRNG(1337) + + bb = parse(Bool, get(ENV, "BB", "false")) ? 9 : nothing + bb_glyph = parse(Bool, get(ENV, "BB_GL", "false")) ? 8 : nothing - bb = parse(Bool, get(ENV, "BB", "false")) ? 9 : nothing - bb_glyph = parse(Bool, get(ENV, "BB_GL", "false")) ? 8 : nothing + banner() """ ) for (i, (k, e)) in enumerate(pairs(exs)) - println(io, "# $k") + println(io, " # $k") code = filter(x -> length(x) != 0 && !startswith(lstrip(x), r"using|import"), [lstrip(c) for c in split(e[2], '\n')]) code = [replace(c, r"\bsprandn\b\(" => "_stable_sprand(rng, ", r"\brandn\b\(" => "randn(rng, ", r"\brand\b\(" => "rand(rng, ") for c in code] println(io, """ - println("ex n°$i - $k") - _ex_$i(rng) = begin - $(indent(join(code, '\n'), 1)) - end - plt = _ex_$i(rng) - display(plt) - savefig(plt, "$ver/$k.png"; transparent=false, bounding_box=bb, bounding_box_glyph=bb_glyph, pixelsize=16) - # savefig(plt, "$ver/$k.txt"; color=true) + println("ex n°$i - $k") + default_size!() + _func_$i(rng) = begin + $(indent(join(code, '\n'), 1)) + end + plt = _func_$i(rng) + display(plt) + savefig(plt, "$ver/$k.png"; transparent=false, bounding_box=bb, bounding_box_glyph=bb_glyph, pixelsize=16) + # savefig(plt, "$ver/$k.txt"; color=true) """ ) end - println(io, "\nreturn\nend\nmain()") + println(io, " return\nend\nmain()") end write(stdout, readme) open("../README.md", "w") do io - write(io, "\n") + write(io, "\n") write(io, readme) end return end main() + +#= +open("imgs/gen_all.sh", "w") do io + write(io, """ + #!/usr/bin/env bash + # $warn + + echo '== julia ==' + \${JULIA-julia} gen_imgs.jl + + txt2png() { + html=\${1%.txt}.html + cat \$1 | \${ANSI2HTML-ansi2html} --input-encoding=utf-8 --output-encoding=utf-8 >\$html + sed -i "s,background-color: #000000,background-color: #282828," \$html + \${WKHTMLTOIMAGE-wkhtmltoimage} --quiet --quality 85 \$html \${html%.html}.png + } + echo '== txt2png ==' + for f in $ver/*.txt; do + txt2png \$f & pids+=(\$!) + done + wait \${pids[@]} + rm $ver/*.txt + rm $ver/*.html + """ + ) +end +=# \ No newline at end of file diff --git a/src/canvas/braillecanvas.jl b/src/canvas/braillecanvas.jl index 5471f6f3..ac4a79db 100644 --- a/src/canvas/braillecanvas.jl +++ b/src/canvas/braillecanvas.jl @@ -50,8 +50,8 @@ function BrailleCanvas( xscale::Function = identity, yscale::Function = identity, ) - width > 0 || throw(ArgumentError("width has to be positive")) - height > 0 || throw(ArgumentError("height has to be positive")) + width > 0 || throw(ArgumentError("`width` has to be positive")) + height > 0 || throw(ArgumentError("`height` has to be positive")) char_width = max(char_width, 5) char_height = max(char_height, 2) pixel_width = char_width * x_pixel_per_char(BrailleCanvas) @@ -75,14 +75,13 @@ function BrailleCanvas( end function pixel_to_char_point(c::BrailleCanvas, pixel_x::Number, pixel_y::Number) + cw, ch = size(c.grid) pixel_x < c.pixel_width || (pixel_x -= 1) pixel_y < c.pixel_height || (pixel_y -= 1) - cw, ch = size(c.grid) - tmp = pixel_x / c.pixel_width * cw - char_x = floor(Int, tmp) + 1 - char_x_off = (pixel_x % 2) + 1 + char_x = floor(Int, pixel_x / c.pixel_width * cw) + 1 + char_x_off = (pixel_x % x_pixel_per_char(BrailleCanvas)) + 1 char_y = floor(Int, pixel_y / c.pixel_height * ch) + 1 - char_y_off = (pixel_y % 4) + 1 + char_y_off = (pixel_y % y_pixel_per_char(BrailleCanvas)) + 1 char_x, char_y, char_x_off, char_y_off end diff --git a/src/canvas/dotcanvas.jl b/src/canvas/dotcanvas.jl index b3fda498..19e17c29 100644 --- a/src/canvas/dotcanvas.jl +++ b/src/canvas/dotcanvas.jl @@ -9,17 +9,13 @@ DOT_DECODE[4] = ':' DOT_DECODE[(N_DOT + 1):typemax(UInt16)] = UNICODE_TABLE[1:(typemax(UInt16) - N_DOT)] """ -Similar to the `AsciiCanvas`, the `DotCanvas` only uses -ASCII characters to draw it's content. Naturally, -it doesn't look quite as nice as the Unicode-based -ones. However, in some situations it might yield -better results. Printing plots to a file is one -of those situations. +Similar to the `AsciiCanvas`, the `DotCanvas` only uses ASCII characters to draw it's content. +Naturally, it doesn't look quite as nice as the Unicode-based ones. +However, in some situations it might yield better results. +Printing plots to a file is one of those situations. -The DotCanvas is best utilized in combination -with `scatterplot`. -For `lineplot` we suggest to use the `AsciiCanvas` -instead. +The DotCanvas is best utilized in combination with `scatterplot`. +For `lineplot` we suggest to use the `AsciiCanvas` instead. """ struct DotCanvas{XS<:Function,YS<:Function} <: LookupCanvas grid::Matrix{UInt16} diff --git a/src/interface/polarplot.jl b/src/interface/polarplot.jl index 832796df..4bfd3da1 100644 --- a/src/interface/polarplot.jl +++ b/src/interface/polarplot.jl @@ -28,24 +28,25 @@ $(arguments( ```julia-repl julia> polarplot(range(0, 2π, length = 20), range(0, 2, length = 20)) - ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ - 2 ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⡤⠤⠒⠒⠉⠉⠉⠉⠉⡏⠉⠉⠉⠉⠓⠒⠦⠤⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ - ⠀⠀⠀⠀⠀⠀⠀⢀⡤⠒⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠒⠤⡀⠀⠀⠀⠀⠀⠀⠀ - ⠀⠀⠀⠀⠀⡠⠞⠓⢄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠜⠓⢄⠀⠀⠀⠀⠀ - ⠀⠀⠀⣠⠊⠀⠀⠀⠀⠉⠢⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⢀⡠⠊⠁⠀⠀⠀⠱⣄⠀⠀⠀ - ⠀⠀⡴⠁⠀⠀⠀⠀⠀⠀⠀⠀⠑⠤⡀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⡠⠔⠁⠀⠀⠀⠀⠀⠀⠀⠈⢦⠀⠀ - ⠀⡸⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣈⠶⢖⠒⠒⠒⠢⣇⡀⠀⠀⢀⠔⠊⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⣇⠀ - ⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠔⠁⠀⠀⠀⠉⠢⣀⠀⡇⢣⡠⠊⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⠀ - ⠀⡧⠤⠤⠤⠤⠤⠤⠤⠤⢤⠧⠤⠤⠤⠤⠤⠤⠤⠤⡵⡷⡭⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⢼⠀ - ⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⢸⠀⠀⠀⠀⠀⠀⢀⠔⠊⠀⡇⠈⠒⢄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⢿⠀ - ⠀⢱⡀⠀⠀⠀⠀⠀⠀⠀⠸⡀⠀⠀⢀⡠⠊⠁⠀⠀⠀⡇⠀⠀⠀⠉⠢⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⢎⡏⠀ - ⠀⠀⠳⡀⠀⠀⠀⠀⠀⠀⠀⠱⡠⠔⠁⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠑⠤⡀⠀⠀⠀⠀⠀⢀⠔⢁⠞⠀⠀ - ⠀⠀⠀⠙⢄⠀⠀⠀⠀⢀⠔⠊⠈⠢⣀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠈⠒⢄⢀⡠⠔⠁⡰⠋⠀⠀⠀ - ⠀⠀⠀⠀⠀⠑⢦⡠⠊⠁⠀⠀⠀⠀⠀⠉⠒⠢⢄⣀⠀⡇⠀⠀⠀⠀⠀⢀⣀⣀⡠⠔⠊⠉⢢⡤⠊⠀⠀⠀⠀⠀ - ⠀⠀⠀⠀⠀⠀⠀⠈⠓⠤⣀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠉⡏⠉⠉⠉⠉⠉⠁⠀⠀⠀⣀⠤⠒⠁⠀⠀⠀⠀⠀⠀⠀ - -2 ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠓⠒⠤⠤⣀⣀⣀⣀⣀⣇⣀⣀⣀⣀⡤⠤⠖⠒⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ - ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ - ⠀-2⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀2⠀ + ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀90°⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ + ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ + ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⡤⠤⠒⠒⠉⠉⠉⠉⠉⡏⠉⠉⠉⠉⠓⠒⠦⠤⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ + ⠀⠀⠀⠀⠀⠀⠀⢀⡤⠒⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠒⠤⡀⠀⠀⠀⠀⠀⠀⠀ + ⠀⠀⠀⠀⠀⡠⠞⠓⢄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠜2⢄⠀⠀⠀⠀⠀ + ⠀⠀⠀⣠⠊⠀⠀⠀⠀⠉⠢⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⢀⡠⠊⠁⠀⠀⠀⠱⣄⠀⠀⠀ + ⠀⠀⡴⠁⠀⠀⠀⠀⠀⠀⠀⠀⠑⠤⡀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀1⠔⠁⠀⠀⠀⠀⠀⠀⠀⠈⢦⠀⠀ + ⠀⡸⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣈⠶⢖⠒⠒⠒⠢⣇⡀⠀⠀⢀⠔⠊⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⣇⠀ + ⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠔⠁⠀⠀⠀⠉⠢⣀⠀⡇⢣⡠⠊⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⠀ + 180° ⠀⡧⠤⠤⠤⠤⠤⠤⠤⠤⢤⠧⠤⠤⠤⠤⠤⠤⠤⠤⡵0⡭⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⢼⠀ 0° + ⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⢸⠀⠀⠀⠀⠀⠀⢀⠔⠊⠀⡇⠈⠒⢄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⢿⠀ + ⠀⢱⡀⠀⠀⠀⠀⠀⠀⠀⠸⡀⠀⠀⢀⡠⠊⠁⠀⠀⠀⡇⠀⠀⠀⠉⠢⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⢎⡏⠀ + ⠀⠀⠳⡀⠀⠀⠀⠀⠀⠀⠀⠱⡠⠔⠁⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠑⠤⡀⠀⠀⠀⠀⠀⢀⠔⢁⠞⠀⠀ + ⠀⠀⠀⠙⢄⠀⠀⠀⠀⢀⠔⠊⠈⠢⣀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠈⠒⢄⢀⡠⠔⠁⡰⠋⠀⠀⠀ + ⠀⠀⠀⠀⠀⠑⢦⡠⠊⠁⠀⠀⠀⠀⠀⠉⠒⠢⢄⣀⠀⡇⠀⠀⠀⠀⠀⢀⣀⣀⡠⠔⠊⠉⢢⡤⠊⠀⠀⠀⠀⠀ + ⠀⠀⠀⠀⠀⠀⠀⠈⠓⠤⣀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠉⡏⠉⠉⠉⠉⠉⠁⠀⠀⠀⣀⠤⠒⠁⠀⠀⠀⠀⠀⠀⠀ + ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠓⠒⠤⠤⣀⣀⣀⣀⣀⣇⣀⣀⣀⣀⡤⠤⠖⠒⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ + ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ + ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀270°⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ """ function polarplot(θ::AbstractVector, 𝓇::Union{Function,AbstractVector}; kw...) diff --git a/src/plot.jl b/src/plot.jl index 3c823590..0d04c28a 100644 --- a/src/plot.jl +++ b/src/plot.jl @@ -643,7 +643,7 @@ function print_labels( right_pad::AbstractString, blank::Char, ) - p.labels || return + p.labels || return 0 bc = BORDER_COLOR[] lloc = Symbol(mloc, :l) rloc = Symbol(mloc, :r) @@ -668,8 +668,9 @@ function print_labels( print_nc(io, pad) print_col(io, right_col, right_str) print_nc(io, right_pad) + return 1 end - nothing + return 0 end Base.show(io::IO, p::Plot) = _show(io, print, print_color, p) @@ -740,7 +741,7 @@ function _show(io::IO, print_nc, print_col, p::Plot) p_width = p_width, color = io_color ? Crayon(foreground = :white, bold = true) : nothing, ) - print_labels( + h_lbl = print_labels( io, print_nc, print_col, @@ -763,7 +764,7 @@ function _show(io::IO, print_nc, print_col, p::Plot) ) # compute position of ylabel - y_lab_row = round(nrows(c) / 2, RoundNearestTiesUp) + y_lab_row = round(nr / 2, RoundNearestTiesUp) callback = colormap_callback(p.colormap) @@ -832,7 +833,7 @@ function _show(io::IO, print_nc, print_col, p::Plot) row < nrows(c) && print_nc(io, '\n') end - # draw bottom border and bottom labels + # draw bottom border c.visible && print_border( io, print_nc, @@ -843,9 +844,10 @@ function _show(io::IO, print_nc, print_col, p::Plot) border_right_pad, bmap, ) - h_lbl = w_lbl = 0 + # print bottom labels + w_lbl = 0 if p.labels - print_labels( + h_lbl += print_labels( io, print_nc, print_col, @@ -856,7 +858,6 @@ function _show(io::IO, print_nc, print_col, p::Plot) 🗹 * border_right_pad, 🗹, ) - h_lbl += 1 if !p.compact h_w = print_title( io, @@ -893,6 +894,8 @@ fallback_font(mono::Bool = false) = end # COV_EXCL_STOP +const FT_FONTS = Dict{String,FreeTypeAbstraction.FTFont}() + """ png_image(p::Plot, font = nothing, pixelsize = 16, transparent = true, foreground = nothing, background = nothing, bounding_box = nothing, bounding_box_glyph = nothing) @@ -1020,9 +1023,12 @@ function png_image( # render image face = nothing - for font_name in filter(!isnothing, (font, "JuliaMono", fallback_font())) - if (ft = FreeTypeAbstraction.findfont(font_name)) ≢ nothing - face = ft + for name in filter(!isnothing, (font, "JuliaMono", fallback_font())) + if haskey(FT_FONTS, name) + face = FT_FONTS[name] + break + elseif (ft = FreeTypeAbstraction.findfont(name)) ≢ nothing + face = FT_FONTS[name] = ft break end end