From 7cac420f6e4e26034dbed83d161177a9423fc8e1 Mon Sep 17 00:00:00 2001
From: Evert Provoost
Date: Mon, 14 Aug 2023 17:07:04 +0200
Subject: [PATCH] Add angle option, and cleanup
---
DomainColoringToy/Project.toml | 4 +-
DomainColoringToy/README.md | 2 +-
DomainColoringToy/src/DomainColoringToy.jl | 12 ++-
Project.toml | 2 +-
docs/src/usage/general.md | 3 +
src/DomainColoring.jl | 97 +++++++++++++---------
6 files changed, 78 insertions(+), 42 deletions(-)
diff --git a/DomainColoringToy/Project.toml b/DomainColoringToy/Project.toml
index 6bca407..aeab9e0 100644
--- a/DomainColoringToy/Project.toml
+++ b/DomainColoringToy/Project.toml
@@ -1,13 +1,13 @@
name = "DomainColoringToy"
uuid = "7cf40ad8-af6a-4ede-b3c6-2a9df3bce851"
authors = ["Evert Provoost "]
-version = "0.2.0"
+version = "0.3.0"
[deps]
DomainColoring = "c24f3079-adb7-4533-8329-9f66732e5e85"
GLMakie = "e9467ef8-e4e7-5192-8a1a-b1aee30e663a"
[compat]
-DomainColoring = "0.4"
+DomainColoring = "0.5"
GLMakie = "0.8"
julia = "1.6"
diff --git a/DomainColoringToy/README.md b/DomainColoringToy/README.md
index 558e852..c68f2f1 100644
--- a/DomainColoringToy/README.md
+++ b/DomainColoringToy/README.md
@@ -9,5 +9,5 @@
Interactive domain colorings and checker plots of complex functions in Julia using smooth colors,
- based on MakieGL.
+ based on GLMakie.
diff --git a/DomainColoringToy/src/DomainColoringToy.jl b/DomainColoringToy/src/DomainColoringToy.jl
index 5eeefff..c51f8dc 100644
--- a/DomainColoringToy/src/DomainColoringToy.jl
+++ b/DomainColoringToy/src/DomainColoringToy.jl
@@ -110,6 +110,7 @@ end
f :: "Complex -> Complex",
limits = (-1, 1, -1, 1);
pixels = (480, 480),
+ angle = true,
abs = false,
grid = false,
all = false,
@@ -137,6 +138,8 @@ to ``\\frac{2\\pi}{3}``, cyan to ``\\pi``, blue to
for both if only one number is provided. If either is `:auto`, the
viewport resolution is used.
+- **`angle`** toggles coloring of the phase angle.
+
- **`abs`** toggles the plotting of the natural logarithm of the
magnitude as lightness ramps between level curves. If set to a number,
this will be used as base of the logarithm instead, if set to `Inf`,
@@ -157,13 +160,20 @@ function domaincolor(
f,
limits = (-1, 1, -1, 1);
pixels = (480, 480),
+ angle = true,
abs = false,
grid = false,
all = false,
)
+ # issue warning if everything is inactive
+ if Base.all(b -> b isa Bool && !b, [angle, abs, grid, all])
+ @warn "angle, abs, and grid are all false, domain coloring will be a constant color."
+ end
+
interactiveshadedplot(
- f, w -> DC.domaincolorshader(w; abs, grid, all), limits, pixels)
+ f, w -> DC.domaincolorshader(w; angle, abs, grid, all),
+ limits, pixels)
end
"""
diff --git a/Project.toml b/Project.toml
index 71f7e38..a7c8f6e 100644
--- a/Project.toml
+++ b/Project.toml
@@ -1,7 +1,7 @@
name = "DomainColoring"
uuid = "c24f3079-adb7-4533-8329-9f66732e5e85"
authors = ["Evert Provoost "]
-version = "0.4.1"
+version = "0.5.0"
[deps]
ColorSchemes = "35d6a980-a343-548e-a6ea-1d62b119f2f4"
diff --git a/docs/src/usage/general.md b/docs/src/usage/general.md
index 7edf27c..4391e8e 100644
--- a/docs/src/usage/general.md
+++ b/docs/src/usage/general.md
@@ -203,3 +203,6 @@ The harshness of these white an black areas can be changed using the
```julia
domaincolor(z -> exp(1/z), .1, abs=(base=Inf, sigma=0.001))
```
+
+Finally, if one wants any of the previous plots without coloring the
+phase angle, they can use `angle = false`.
diff --git a/src/DomainColoring.jl b/src/DomainColoring.jl
index 9d33c1e..a6da1bc 100644
--- a/src/DomainColoring.jl
+++ b/src/DomainColoring.jl
@@ -118,20 +118,24 @@ function shadedplot(
limits = _expandlimits(limits)
- r = [limits[1], limits[2]]
- i = [limits[3], limits[4]]
# images have inverted y and flip x and y in their storage
- heatmap(r, reverse(i), renderimage(f, shader, limits, pixels)';
+ r = [limits[1], limits[2]]
+ i = [limits[4], limits[3]]
+ heatmap(r, i, renderimage(f, shader, limits, pixels)';
interpolate=true, axis=(autolimitaspect=1,),)
end
+@enum GridType begin
+ CheckerGrid
+ LineGrid
+end
# Logic for grid like plotting elements, somewhat ugly, but it works.
-# `w` is the complex value, `checker` is a boolean for the others see
+# `w` is the complex value, `type` is the type of grid to make
# `checkerplot`.
function _grid(
- w,
- checker;
+ type,
+ w;
real = false,
imag = false,
rect = false,
@@ -175,38 +179,45 @@ function _grid(
end
# set defaults
- (real isa Bool && real) && (real = 1)
- (imag isa Bool && imag) && (imag = 1)
+ (real isa Bool && real) && (real = 1)
+ (imag isa Bool && imag) && (imag = 1)
(angle isa Bool && angle) && (angle = 6)
- (abs isa Bool && abs) && (abs = 1)
+ (abs isa Bool && abs) && (abs = 1)
g = 1.0
- if real > 0 && isfinite(4*real*Base.real(w))
- g *= sin(real*π*Base.real(w))
+ if real > 0
+ r = real * π * Base.real(w)
+ isfinite(r) && (g *= sin(r))
end
- if imag > 0 && isfinite(4*imag*Base.imag(w))
- g *= sin(imag*π*Base.imag(w))
+ if imag > 0
+ i = imag * π * Base.imag(w)
+ isfinite(i) && (g *= sin(i))
end
- if angle > 0 && isfinite(angle*Base.angle(w))
- checker && @assert iseven(angle) "Rate of angle has to be even."
- g *= sin(angle/2*Base.angle(w))
+ if angle > 0
+ @assert mod(angle, 1) ≈ 0 "Rate of angle has to be an integer."
+ angle = round(angle)
+ (type == CheckerGrid) && @assert iseven(angle) "Rate of angle has to be even."
+
+ a = angle / 2 * Base.angle(w)
+ isfinite(a) && (g *= sin(a))
end
- if abs > 0 && isfinite(4*abs*log(Base.abs(w)))
- g *= sin(abs*π*log(Base.abs(w)))
+ if abs > 0
+ m = abs * π * log(Base.abs(w))
+ isfinite(m) && (g *= sin(m))
end
- if checker
- min(1, sign(g) + 1)
- else
+ if type == CheckerGrid
+ float(g > 0)
+ elseif type == LineGrid
Base.abs(g)^0.06
end
end
-_grid(w, checker, args::NamedTuple) = _grid(w, checker; args...)
+_grid(type, w, args::NamedTuple) = _grid(type, w; args...)
-_grid(w, checker, arg::Bool) = arg ? _grid(w, checker) : 1.0
+_grid(type, w, arg::Bool) = arg ? _grid(type, w) : 1.0
-_grid(w, checker, arg) = _grid(w, checker; rect=arg)
+_grid(type, w, arg) = _grid(type, w; rect=arg)
# Implements the magnitude logic for `domaincolorshader`
# isnothing(transform) gives the default log, and saves us
@@ -215,7 +226,7 @@ _grid(w, checker, arg) = _grid(w, checker; rect=arg)
function _add_magnitude(
w,
c;
- base = exp(1),
+ base = ℯ,
transform = nothing,
sigma = 0.02,
)
@@ -231,11 +242,9 @@ function _add_magnitude(
isfinite(m) && (c = Lab(c.l + 20mod(m, 1) - 10, c.a, c.b))
else
m = log(abs(w))
- if isfinite(m)
- t = exp(-sigma*m^2)
- g = 100(sign(m)/2 + .5)
- c = Lab((1 - t)g + t*c.l, t*c.a, t*c.b)
- end
+ t = isfinite(m) ? exp(-sigma*m^2) : 0.0
+ g = 100.0(m > 0)
+ c = Lab((1 - t)g + t*c.l, t*c.a, t*c.b)
end
end
return c
@@ -265,12 +274,15 @@ See [Phase Wheel](@ref) for more information.
"""
function labsweep(θ)
θ = mod(θ, 2π)
- Lab(67 - 12cos(3θ), 46cos(θ + .4) - 3, 46sin(θ + .4) + 16)
+ Lab(67 - 12cos(3θ),
+ 46cos(θ + .4) - 3,
+ 46sin(θ + .4) + 16)
end
"""
DomainColoring.domaincolorshader(
w :: Complex;
+ angle = true,
abs = false,
grid = false,
all = false,
@@ -282,6 +294,7 @@ For documentation of the remaining arguments see [`domaincolor`](@ref).
"""
function domaincolorshader(
w;
+ angle = true,
abs = false,
grid = false,
all = false,
@@ -289,12 +302,13 @@ function domaincolorshader(
# user wants full domain coloring
if all
- abs = true
- grid = true
+ (angle isa Bool) && (angle = true)
+ (abs isa Bool) && (abs = true)
+ (grid isa Bool) && (grid = true)
end
# phase color
- c = labsweep(angle(w))
+ c = angle ? labsweep(Base.angle(w)) : Lab(80.0, 0.0, 0.0)
# add magnitude
c = _add_magnitude(w, c, abs)
@@ -302,7 +316,7 @@ function domaincolorshader(
# add integer grid if requested
if !(grid isa Bool) || grid
# slightly overattenuate to compensate global darkening
- g = 1.06_grid(w, false, grid)
+ g = 1.06_grid(LineGrid, w, grid)
c = mapc(x -> g*x, c)
end
@@ -314,6 +328,7 @@ end
f :: "Complex -> Complex",
limits = (-1, 1, -1, 1);
pixels = (720, 720),
+ angle = true,
abs = false,
grid = false,
all = false,
@@ -340,6 +355,8 @@ to ``\\frac{2\\pi}{3}``, cyan to ``\\pi``, blue to
real and imaginary axis, taking the same for both if only one number
is provided.
+- **`angle`** toggles coloring of the phase angle.
+
- **`abs`** toggles the plotting of the natural logarithm of the
magnitude as lightness ramps between level curves. If set to a number,
this will be used as base of the logarithm instead, if set to `Inf`,
@@ -360,13 +377,19 @@ function domaincolor(
f,
limits = (-1, 1, -1, 1);
pixels = (720, 720),
+ angle = true,
abs = false,
grid = false,
all = false,
)
+ # issue warning if everything is inactive
+ if Base.all(b -> b isa Bool && !b, [angle, abs, grid, all])
+ @warn "angle, abs, and grid are all false, domain coloring will be a constant color."
+ end
+
shadedplot(f, w -> domaincolorshader(
- w; abs, grid, all
+ w; angle, abs, grid, all
), limits, pixels)
end
@@ -497,7 +520,7 @@ function checkerplotshader(
polar = false,
)
- g = _grid(w, true; real, imag, rect, angle, abs, polar)
+ g = _grid(CheckerGrid, w; real, imag, rect, angle, abs, polar)
return Gray(0.9g + 0.08)
end