From b7e0d62ab839112a1ef84ecba82ab666527eb34f Mon Sep 17 00:00:00 2001 From: Evert Provoost Date: Wed, 6 Sep 2023 17:18:36 +0200 Subject: [PATCH] Added box option --- DomainColoringToy/src/DomainColoringToy.jl | 41 ++++++- docs/src/usage/general.md | 21 +++- src/DomainColoring.jl | 121 ++++++++++++++++++--- 3 files changed, 159 insertions(+), 24 deletions(-) diff --git a/DomainColoringToy/src/DomainColoringToy.jl b/DomainColoringToy/src/DomainColoringToy.jl index 78fa945..5662ee8 100644 --- a/DomainColoringToy/src/DomainColoringToy.jl +++ b/DomainColoringToy/src/DomainColoringToy.jl @@ -125,6 +125,7 @@ end grid = false, color = true, all = false, + box = nothing, kwargs... ) @@ -169,6 +170,10 @@ to ``\\frac{2\\pi}{3}``, cyan to ``\\pi``, blue to - **`all`** is a shortcut for `abs = true` and `grid = true`. +- **`box`** if set to `(a, b, s)` shades the area where the the output + is within the box `a` and `b` in the color `s`. Can also be a list of + multiple boxes. + Remaining keyword arguments are passed to Makie. """ function domaincolor( @@ -179,6 +184,7 @@ function domaincolor( grid = false, color = true, all = false, + box = nothing, kwargs... ) @@ -188,7 +194,7 @@ function domaincolor( end interactiveshadedplot( - f, w -> DC.domaincolorshader(w; abs, grid, color, all), + f, w -> DC.domaincolorshader(w; abs, grid, color, all, box), limits, pixels; kwargs...) end @@ -197,6 +203,7 @@ end f :: "Complex -> Complex", limits = (-1, 1, -1, 1); pixels = (480, 480), + box = nothing, kwargs... ) @@ -222,16 +229,21 @@ to ``\\pi``, and black to ``\\frac{3\\pi}{2}``. for both if only one number is provided. If either is `:auto`, the viewport resolution is used. +- **`box`** if set to `(a, b, s)` shades the area where the the output + is within the box `a` and `b` in the color `s`. Can also be a list of + multiple boxes. + Remaining keyword arguments are passed to Makie. """ function pdphaseplot( f, limits = (-1, 1, -1, 1); pixels = (480, 480), + box = nothing, kwargs... ) - interactiveshadedplot(f, DC.pdphaseplotshader, + interactiveshadedplot(f, w -> DC.pdphaseplotshader(w; box), limits, pixels; kwargs...) end @@ -240,6 +252,7 @@ end f :: "Complex -> Complex", limits = (-1, 1, -1, 1); pixels = (480, 480), + box = nothing, kwargs... ) @@ -265,16 +278,21 @@ Red corresponds to phase ``0``, white to ``\\frac{\\pi}{2}``, cyan to for both if only one number is provided. If either is `:auto`, the viewport resolution is used. +- **`box`** if set to `(a, b, s)` shades the area where the the output + is within the box `a` and `b` in the color `s`. Can also be a list of + multiple boxes. + Remaining keyword arguments are passed to Makie. """ function tphaseplot( f, limits = (-1, 1, -1, 1); pixels = (480, 480), + box = nothing, kwargs... ) - interactiveshadedplot(f, DC.tphaseplotshader, + interactiveshadedplot(f, w -> DC.tphaseplotshader(w; box), limits, pixels; kwargs...) end @@ -289,6 +307,8 @@ end angle = false, abs = false, polar = false, + box = nothing, + hicontrast = false, kwargs... ) @@ -329,6 +349,10 @@ Numbers can be provided instead of booleans to override the default rates. - **`phase`** is a shortcut for `angle = true` and `abs = true`. +- **`box`** if set to `(a, b, s)` shades the area where the the output + is within the box `a` and `b` in the color `s`. Can also be a list of + multiple boxes. + - **`hicontrast`** uses black and white instead of the softer defaults. Remaining keyword arguments are passed to Makie. @@ -343,12 +367,13 @@ function checkerplot( angle = false, abs = false, polar = false, + box = nothing, hicontrast = false, kwargs... ) interactiveshadedplot(f, w -> DC.checkerplotshader( - w; real, imag, rect, angle, abs, polar, hicontrast + w; real, imag, rect, angle, abs, polar, box, hicontrast ), limits, pixels; kwargs...) end @@ -364,6 +389,7 @@ end abs = false, polar = false, color = false, + box = nothing, kwargs... ) @@ -406,6 +432,10 @@ Numbers can be provided instead of booleans to override the default rates. - **`color`** toggles coloring of the phase angle. Can also be set to either the name of, or a `ColorScheme`, or a function `θ -> Color`. +- **`box`** if set to `(a, b, s)` shades the area where the the output + is within the box `a` and `b` in the color `s`. Can also be a list of + multiple boxes. + Remaining keyword arguments are passed to Makie. """ function sawplot( @@ -419,11 +449,12 @@ function sawplot( abs = false, polar = false, color = false, + box = nothing, kwargs... ) interactiveshadedplot(f, w -> DC.sawplotshader( - w; real, imag, rect, angle, abs, polar, color + w; real, imag, rect, angle, abs, polar, color, box ), limits, pixels; kwargs...) end diff --git a/docs/src/usage/general.md b/docs/src/usage/general.md index cc63c3f..19ecf17 100644 --- a/docs/src/usage/general.md +++ b/docs/src/usage/general.md @@ -22,6 +22,10 @@ All plots have a keyword argument `pixels` by which one can specify the number of samples in respectively the real and imaginary direction. If only one number is provided it is used for both. +Additionally there is also the option to fill in a box, or list of boxes +in the output space using the option `box`, which is illustrated in the +section on [`checkerplot`](@ref) and [`sawplot`](@ref). + Finally, any remaining keywords are passed to Makie. This, together with the modifying variants (`domaincolor!`, `checkerplot!`, etc.), makes the plotting routines in this library behave similarly to other Makie plot @@ -151,7 +155,7 @@ discussed so far also accept numbers, modifying the rate of the stripes. For example, we get for magnitude: ```@example using CairoMakie, DomainColoring # hide -checkerplot(z -> z, 5, abs=5) +sawplot(z -> z, 5, abs=5) resize!(current_figure(), 620, 600) #hide save("cpabs.png", current_figure()) # hide nothing # hide @@ -162,7 +166,7 @@ and for phase: ```@example using CairoMakie, DomainColoring # hide -sawplot(z -> z, 5, angle=10) +checkerplot(z -> z, 5, angle=10) resize!(current_figure(), 620, 600) #hide save("cpangle.png", current_figure()) # hide nothing # hide @@ -181,6 +185,17 @@ nothing # hide ``` ![](cppolarsin.png) +As mentioned before regions of the output plane can be colored using the +`box` option, for example: +```@example +using CairoMakie, DomainColoring # hide +checkerplot(z -> z^2, 2, box=[(1,1im,:red), (-1-2im,-2-1im,:blue)]) +resize!(current_figure(), 620, 600) #hide +save("cpboxes.png", current_figure()) # hide +nothing # hide +``` +![](cpboxes.png) + Finally, `hicontrast = true` can be used in [`checkerplot`](@ref) to plot in black and white instead of the slightly softer defaults, and `color = true` mixes phase coloring into a [`sawplot`](@ref) (further @@ -195,7 +210,7 @@ and the rate of the grid. Additionally, we can pass named tuples to open up even more options. For `grid` these options are identical to `checkerplot`, for example an -analogous example to the final one of last section, is given by: +analogous example to the penultimate one of last section, is given by: ```@example using CairoMakie, DomainColoring # hide domaincolor(sin, (5, 2), grid=(polar=4,)) diff --git a/src/DomainColoring.jl b/src/DomainColoring.jl index 1e4ba98..54ca053 100644 --- a/src/DomainColoring.jl +++ b/src/DomainColoring.jl @@ -383,6 +383,31 @@ _add_magnitude(w, c, arg::Function) = _add_magnitude(w, c; transform=arg) _add_magnitude(w, c, arg) = _add_magnitude(w, c; base=arg) +# draw a colored box in a specified area +function _add_box(w, c, sqs) + if isnothing(sqs) + return c + end + + for sq in sqs + c = _add_box(w, c, sq) + end + return c +end + +function _add_box(w, c::C, sq::Tuple{<:Any, <:Any, <:Color}) where C <: Color + a, b, s = sq + r, i = reim(w) + mr, Mr = minmax(real(a), real(b)) + mi, Mi = minmax(imag(a), imag(b)) + (mr <= r <= Mr) && (mi <= i <= Mi) ? convert(C, s) : c +end + +function _add_box(w, c::C, sq::Tuple{<:Any, <:Any, <:Any}) where C <: Color + a, b, s = sq + _add_box(w, c, (a, b, parse(C, s))) +end + """ DomainColoring.domaincolorshader( w :: Complex; @@ -390,6 +415,7 @@ _add_magnitude(w, c, arg) = _add_magnitude(w, c; base=arg) grid = false, color = true, all = false, + box = nothing, ) Takes a complex value **`w`** and shades it as in a domain coloring. @@ -402,6 +428,7 @@ function domaincolorshader( grid = false, color = true, all = false, + box = nothing, ) # user wants full domain coloring @@ -413,7 +440,7 @@ function domaincolorshader( # short circuit conversions if (abs isa Bool) && !abs && (grid isa Bool) && !grid - return _color_angle(w, color) + return _add_box(w, _color_angle(w, color), box) end # phase color @@ -429,6 +456,9 @@ function domaincolorshader( c = mapc(x -> g*x, c) end + # add boxs + c = _add_box(w, c, box) + return c end @@ -443,6 +473,7 @@ export domaincolor, domaincolor! grid = false, color = true, all = false, + box = nothing, kwargs... ) @@ -487,6 +518,10 @@ to ``\\frac{2\\pi}{3}``, cyan to ``\\pi``, blue to - **`all`** is a shortcut for `abs = true`, `grid = true`, and `color = true`. +- **`box`** if set to `(a, b, s)` shades the area where the the output + is within the box `a` and `b` in the color `s`. Can also be a list of + multiple boxes. + Remaining keyword arguments are passed to Makie. """ domaincolor, domaincolor! @@ -496,17 +531,21 @@ domaincolor, domaincolor! (abs = false, grid = false, color = true, - all = false), + all = false, + box = nothing), begin # issue warning if everything is inactive if Base.all(b -> b isa Bool && !b, (abs, grid, color, all)) @warn "angle, abs, and grid are all false, domain coloring will be a constant color." end - w -> domaincolorshader(w; abs, grid, color, all) + w -> domaincolorshader(w; abs, grid, color, all, box) end) """ - DomainColoring.pdphaseplotshader(w :: Complex) + DomainColoring.pdphaseplotshader( + w :: Complex; + box = nothing, + ) Shades a complex value **`w`** as a phase plot using [ColorCET](https://colorcet.com)'s CBC1 cyclic color map for @@ -514,7 +553,13 @@ protanopic and deuteranopic viewers. See [`pdphaseplot`](@ref) for more information. """ -pdphaseplotshader(w) = _color_angle(w, :CBC1) +function pdphaseplotshader( + w; + box = nothing, + ) + + _add_box(w, _color_angle(w, :CBC1), box) +end export pdphaseplot, pdphaseplot! @@ -523,6 +568,7 @@ export pdphaseplot, pdphaseplot! f :: "Complex -> Complex", limits = (-1, 1, -1, 1); pixels = (720, 720), + box = nothing, kwargs... ) @@ -547,14 +593,23 @@ to ``\\pi``, and black to ``\\frac{3\\pi}{2}``. real and imaginary axis, taking the same for both if only one number is provided. +- **`box`** if set to `(a, b, s)` shades the area where the the output + is within the box `a` and `b` in the color `s`. Can also be a list of + multiple boxes. + Remaining keyword arguments are passed to Makie. """ pdphaseplot, pdphaseplot! -@shadedplot(pdphaseplot, (), pdphaseplotshader) +@shadedplot(pdphaseplot, + (box = nothing,), + w -> pdphaseplotshader(w; box)) """ - DomainColoring.tphaseplotshader(w :: Complex) + DomainColoring.tphaseplotshader( + w :: Complex; + box = nothing, + ) Shades a complex value **`w`** as a phase plot using [ColorCET](https://colorcet.com)'s CBTC1 cyclic color map for @@ -562,7 +617,13 @@ titranopic viewers. See [`tphaseplot`](@ref) for more information. """ -tphaseplotshader(w) = _color_angle(w, :CBTC1) +function tphaseplotshader( + w; + box = nothing, + ) + + _add_box(w, _color_angle(w, :CBTC1), box) +end export tphaseplot, tphaseplot! @@ -571,6 +632,7 @@ export tphaseplot, tphaseplot! f :: "Complex -> Complex", limits = (-1, 1, -1, 1); pixels = (720, 720), + box = nothing, kwargs... ) @@ -595,11 +657,17 @@ Red corresponds to phase ``0``, white to ``\\frac{\\pi}{2}``, cyan to real and imaginary axis, taking the same for both if only one number is provided. +- **`box`** if set to `(a, b, s)` shades the area where the the output + is within the box `a` and `b` in the color `s`. Can also be a list of + multiple boxes. + Remaining keyword arguments are passed to Makie. """ tphaseplot, tphaseplot! -@shadedplot(tphaseplot, (), tphaseplotshader) +@shadedplot(tphaseplot, + (box = nothing,), + w -> tphaseplotshader(w; box)) """ DomainColoring.checkerplotshader( @@ -610,6 +678,7 @@ tphaseplot, tphaseplot! angle = false, abs = false, polar = false, + box = nothing, hicontrast = false, ) @@ -625,16 +694,20 @@ function checkerplotshader( angle = false, abs = false, polar = false, + box = nothing, hicontrast = false, ) g = _grid(CheckerGrid, w; real, imag, rect, angle, abs, polar) if hicontrast - Gray(g) + c = Gray(g) else - Gray(0.9g + 0.08) + c = Gray(0.9g + 0.08) end + + # add boxs + isnothing(box) ? c : _add_box(w, convert(RGB, c), box) end export checkerplot, checkerplot! @@ -650,6 +723,7 @@ export checkerplot, checkerplot! angle = false, abs = false, polar = false, + box = nothing, hicontrast = false, kwargs... ) @@ -689,6 +763,10 @@ Numbers can be provided instead of booleans to override the default rates. - **`phase`** is a shortcut for `angle = true` and `abs = true`. +- **`box`** if set to `(a, b, s)` shades the area where the the output + is within the box `a` and `b` in the color `s`. Can also be a list of + multiple boxes. + - **`hicontrast`** uses black and white instead of the softer defaults. Remaining keyword arguments are passed to Makie. @@ -702,9 +780,10 @@ checkerplot, checkerplot! angle = false, abs = false, polar = false, + box = nothing, hicontrast = false), w -> checkerplotshader( - w; real, imag, rect, angle, abs, polar, hicontrast + w; real, imag, rect, angle, abs, polar, box, hicontrast )) """ @@ -717,6 +796,7 @@ checkerplot, checkerplot! abs = false, polar = false, color = false, + box = nothing, ) Takes a complex value **`w`** and shades it as in a saw plot. @@ -732,15 +812,18 @@ function sawplotshader( abs = false, polar = false, color = false, + box = nothing, ) g = _grid(SawGrid, w; real, imag, rect, angle, abs, polar) if color isa Bool && !color - Gray(0.6g + 0.3) + c = Gray(0.6g + 0.3) + isnothing(box) ? c : _add_box(w, convert(RGB, c), box) else c = convert(Lab, _color_angle(w, color)) - Lab(c.l + 20g - 10, c.a, c.b) + c = Lab(c.l + 20g - 10, c.a, c.b) + _add_box(w, c, box) end end @@ -758,6 +841,7 @@ export sawplot, sawplot! abs = false, polar = false, color = false, + box = nothing, kwargs... ) @@ -799,6 +883,10 @@ Numbers can be provided instead of booleans to override the default rates. - **`color`** toggles coloring of the phase angle. Can also be set to either the name of, or a `ColorScheme`, or a function `θ -> Color`. +- **`box`** if set to `(a, b, s)` shades the area where the the output + is within the box `a` and `b` in the color `s`. Can also be a list of + multiple boxes. + Remaining keyword arguments are passed to Makie. """ sawplot, sawplot! @@ -810,9 +898,10 @@ sawplot, sawplot! angle = false, abs = false, polar = false, - color = false), + color = false, + box = nothing), w -> sawplotshader( - w; real, imag, rect, angle, abs, polar, color + w; real, imag, rect, angle, abs, polar, color, box )) end