Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PolarAxis unable to set negative rlimits #3375

Closed
3 tasks done
mikeingold opened this issue Nov 15, 2023 · 1 comment · Fixed by #3381
Closed
3 tasks done

PolarAxis unable to set negative rlimits #3375

mikeingold opened this issue Nov 15, 2023 · 1 comment · Fixed by #3381
Labels
enhancement Feature requests and enhancements

Comments

@mikeingold
Copy link

  • are you running newest version (version from docs) ?
  • can you reproduce the bug with a fresh environment ? (]activate --temp; add Makie)
  • What platform + GPU are you on?
julia> versioninfo()
Julia Version 1.9.4
Commit 8e5136fa29 (2023-11-14 08:46 UTC)
Build Info:
  Official https://julialang.org/ release
Platform Info:
  OS: Windows (x86_64-w64-mingw32)
  CPU: 32 × AMD Ryzen 9 3950X 16-Core Processor
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-14.0.6 (ORCJIT, znver2)
  Threads: 16 on 32 virtual cores
Environment:
  JULIA_NUM_THREADS = 16

Issue

It looks like PolarAxis does not support setting negative r limits or plotting lines with negative values. Polar plots are used frequently in electrical engineering to present things like antenna gain patterns, measured on a dB scale (Example).

I demonstrated this with the MWE below, plotting a fake gain pattern in linear and dB scales on both a regular Axis and a PolarAxis. The polar plot in dB scale won't display any of the line because it's always <= 0. If I try to set rlimits to the appropriate range for this plot, e.g. rlimits=(-40,0) the r axis looks like a mess with no ticks remaining.

Minimum Working Example

using CairoMakie

pow2db(x) = 20log10(x)

theta_prime = pi
angle(a,b) = min(abs(a-b), 2π-abs(a-b))
gain(theta) = abs(sinc(2.0*angle(theta,theta_prime)))

thetas = range(0, 2pi, length=361)
# Axis plots in linear and dB scale
f_xy = Figure()
ax_xy_lin = Axis(f_xy[1,1], title="Gain", xlabel="Theta [rad]")
lines!(ax_xy_lin, thetas, gain.(thetas))
ax_xy_dB = Axis(f_xy[1,2], title="Gain in dB", xlabel="Theta [rad]")
lines!(ax_xy_dB, thetas, pow2db.(gain.(thetas)))
save("f_xy.png", f_xy)

f_xy

# PolarAxis plots in linear and dB scale
f_polar = Figure()
ax_polar_lin = PolarAxis(f_polar[1,1], title="Gain")
lines!(ax_polar_lin, thetas, gain.(thetas))
ax_polar_dB = PolarAxis(f_polar[1,2], title="Gain in dB")
lines!(ax_polar_dB, thetas, pow2db.(gain.(thetas)))
save("f_polar.png", f_polar)

f_polar

@mikeingold mikeingold added the bug label Nov 15, 2023
@ffreyer
Copy link
Collaborator

ffreyer commented Nov 15, 2023

We experimented with offsetting radii so that r_in > 0 ends up at r_out = 0 to increase the space a plot limited to a ring (sector) occupies. (I.e. with rmax > rmin >> 0.) That's what radial_distortion_threshold is about. With r_out = r_in - r0 it sets a limit for how large (r_min - r0) / (r_max - r0) is allowed to get, calculating the r0.

Ultimately this won't help you, since it is restricted to r0 > 0. I also don't think you can hack this by setting r0 in ax.scene.transformation.transform_func, because of how the updates are set up and because PolarAxis probably assumes positive radii at times.

But there is still some functionality for this in the background and I think replacing radial_distortion_threshold with directly setting r0 wouldn't be a bad idea. It seems easier to understand to me and more useful.

If you want to try making these changes you could remove

# To keep the inner clip radius below a certain fraction of the outer clip
# radius we map all r > r0 to 0. This computes that r0.
radius_at_origin = map(po.blockscene, po.target_rlims, po.radial_distortion_threshold) do (rmin, rmax), max_fraction
# max_fraction = (rmin - r0) / (rmax - r0) solved for r0
return max(0.0, (rmin - max_fraction * rmax) / (1 - max_fraction))
end

and make radius_at_origin (the r0) an attribute of the PolarAxis by adding it here
"The direction of rotation. Can be -1 (clockwise) or 1 (counterclockwise)."
direction::Int = 1
"The angular offset for (1, 0) in the PolarAxis. This rotates the axis."
theta_0::Float32 = 0f0
"Controls the argument order of the Polar transform. If `theta_as_x = true` it is (θ, r), otherwise (r, θ)."
theta_as_x::Bool = true
"The relative margins added to the autolimits in r direction."

The radial_distortion_threshold further above should be removed as well.

@ffreyer ffreyer added enhancement Feature requests and enhancements and removed bug labels Nov 15, 2023
SimonDanisch added a commit that referenced this issue Nov 20, 2023
…origin (#3381)

# Description

Fixes #3375 by allowing users to set a radial offset that can be used to
map a negative rmin to 0. E.g.:
```julia
pow2db(x) = 20log10(x)    
theta_prime = pi
angle(a,b) = min(abs(a-b), 2π-abs(a-b))
gain(theta) = abs(sinc(2.0*angle(theta,theta_prime)))

thetas = range(0, 2pi, length=361)
rs = pow2db.(gain.(thetas))

f_polar = Figure()
ax_polar_lin = PolarAxis(f_polar[1,1], title="Gain")
lines!(ax_polar_lin, thetas, gain.(thetas))
ax_polar_dB = PolarAxis(f_polar[1,2], title="Gain in dB", radius_at_origin = -80)
lines!(ax_polar_dB, thetas, rs)
f_polar
```

![Screenshot from 2023-11-17
14-46-38](https://github.com/MakieOrg/Makie.jl/assets/10947937/d3933529-0705-4a28-844e-27dfbce9f6ff)

Some open questions:
- Should negative rlimits automatically result in radii getting shifted?
- Should zooming be allowed to change `radius_at_origin`?
- Should we adjust `theta_0` to work like r0/radius_at_origin? Currently
we have `theta_out = theta_in + theta_0` and `r_out = r_in - r0`

Note that offsetting radii results in distortions:
```julia
phis = range(pi/4, 9pi/4, length=201)
rs = 1.0 ./ sin.(range(pi/4, 3pi/4, length=51)[1:end-1])
rs = vcat(rs, rs, rs, rs, rs[1])

fig = Figure()
ax = PolarAxis(fig[1, 1], radius_at_origin = -2)
lines!(ax, phis, rs)
ax = PolarAxis(fig[1, 2])
lines!(ax, phis, rs)
ax = PolarAxis(fig[1, 3], radius_at_origin = 0.5)
lines!(ax, phis, rs)
fig
```

![Screenshot from 2023-11-17
14-57-01](https://github.com/MakieOrg/Makie.jl/assets/10947937/a6390ba2-526d-4fcb-8702-69e8d89e206f)

## Changes

- replace `radial_distortion_threshold` with `radius_at_origin` which
allows you to set an offset for radii
- add `clip_r::Bool` to PolarAxis and Polar transform, allowing you to
set whether to enforce $r \ge 0$ or not
- for `clip_r = true` (old behavior) return `NaN` rather than `r = 0` if
$r < 0$.

## Type of change

- [x] (Somewhat minor) Breaking change (fix or feature that would cause
existing functionality to not work as expected)

## Checklist

- [x] Added an entry in NEWS.md (for new features and breaking changes)
- [x] Added or changed relevant sections in the documentation
- [x] Added unit tests for new algorithms, conversion methods, etc.
- [x] Added reference image tests for new plotting functions, recipes,
visual options, etc.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement Feature requests and enhancements
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants