Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 0 additions & 6 deletions .JuliaFormatter.toml

This file was deleted.

8 changes: 6 additions & 2 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,15 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [2.3.6] unreleased
## [2.4.0] 03/06/2026

### Added

* an extension to also perform the numerical checks plots with [`Makie.jl](https://https://makie.org/) (#272).

### Fixed

* (documentation of the `injectivity_radius` function now displays clearer instructions for the implementation of a radius linked to a user's own `AbstractRetractionMethod`. (#270)
* documentation of the `injectivity_radius` function now displays clearer instructions for the implementation of a radius linked to a user's own `AbstractRetractionMethod`. (#270)

## [2.3.5] 03/04/2026

Expand Down
9 changes: 7 additions & 2 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,36 +1,41 @@
name = "ManifoldsBase"
uuid = "3362f125-f0bb-47a3-aa74-596ffd7ef2fb"
version = "2.4.0"
authors = ["Seth Axen <seth.axen@gmail.com>", "Mateusz Baran <mateuszbaran89@gmail.com>", "Ronny Bergmann <manopt@ronnybergmann.net>", "Antoine Levitt <antoine.levitt@gmail.com>"]
version = "2.3.5"

[workspace]
projects = ["test", "docs", "tutorials"]

[deps]
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
Markdown = "d6f4376e-aef5-505a-96c1-9c027394607a"
Preferences = "21216c6a-2e73-6563-6e65-726566657250"
Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"

[weakdeps]
Makie = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a"
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
Quaternions = "94ee1d12-ae83-5a48-8b1c-48b8ff168ae0"
RecursiveArrayTools = "731186ca-8d62-57ce-b412-fbd966d074cd"
Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"

[extensions]
ManifoldsBaseMakieExt = "Makie"
ManifoldsBasePlotsExt = "Plots"
ManifoldsBaseQuaternionsExt = "Quaternions"
ManifoldsBaseRecursiveArrayToolsExt = "RecursiveArrayTools"
ManifoldsBaseStatisticsExt = "Statistics"

[compat]
LinearAlgebra = "1.6"
Makie = "0.24"
Markdown = "1.6"
Plots = "1"
Preferences = "1.4"
Printf = "1.6"
Quaternions = "0.7"
Random = "1.6"
RecursiveArrayTools = "2, 3, 4"
Quaternions = "0.7"
Statistics = "1.6"
julia = "1.10"
4 changes: 3 additions & 1 deletion docs/src/index.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# ManifoldsBase.jl

`ManifoldsBase.jl` is a lightweight interface for manifolds.
```@docs
ManifoldsBase.ManifoldsBase
```

This packages has two main purposes.
You can add it as a dependency if you plan to work on manifolds (generically) or if you plan to
Expand Down
63 changes: 63 additions & 0 deletions ext/ManifoldsBaseMakieExt.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
module ManifoldsBaseMakieExt

using ManifoldsBase
using Makie
using Printf: @sprintf
import ManifoldsBase: plot_slope, plot_check_geodesic

function ManifoldsBase.plot_slope(
::Val{:Makie}, x, y;
slope = 2, line_base = 0, a = 0, b = 2.0, i = 1, j = length(x),
)
fig = Makie.Figure()
# Setup the log log plot
ax = Makie.Axis(
fig[1, 1];
xscale = log10, yscale = log10, xlabel = "t", ylabel = L"E(t)", title = "Slope plot",
)
# Main error data
Makie.lines!(ax, x, y; label = L"E(t)", linewidth = 3, color = :lightblue)
# Reference slope
s_line = [exp10(line_base + t * slope) for t in log10.(x)]
Makie.lines!(
ax, x, s_line; label = "slope s=$slope",
linestyle = :dash, color = :black, linewidth = 2
)

# Best-fit slope segment if i and j are provided
if (i != 0) && (j != 0)
best_line = [exp10(a + t * b) for t in log10.(x[i:j])]
Makie.lines!(
ax, x[i:j], best_line;
label = "best slope $(@sprintf("%.4f", b))",
color = :blue, linestyle = :dot, linewidth = 2,
)
end
Makie.axislegend(ax; position = :lt)
return fig
end
function ManifoldsBase.plot_check_geodesic(::Val{:Makie}, T, N, e_norm, e_pt, e_alpha)
fig = Figure()
ax = Axis(
fig[1, 1];
xlabel = "t", ylabel = "error magnitude", title = "Geodesic checks",
)
# Speed deviation: |‖Xᵢ‖ − mean‖X‖|
Makie.lines!(
ax, T[1:(N - 1)], e_norm;
label = L"|\|X_i\| - \overline{\|X\|}|", linewidth = 3, color = :lightblue
)
# Parallel-transport mismatch (norm): ‖Xᵢ − PT_{i+1→i}(X_{i+1})‖
lines!(
ax, T[1:(N - 2)], e_pt;
label = "PT difference (norm)", linewidth = 3, color = :blue
)
# Parallel-transport mismatch (angle): |1 − cos∠(Xᵢ, PT_{i+1→i}X_{i+1})|
lines!(
ax, T[1:(N - 2)], e_alpha;
label = "PT difference (angle)", linewidth = 3, color = :green
)
axislegend(ax; position = :rt)
return fig
end
end
40 changes: 9 additions & 31 deletions ext/ManifoldsBasePlotsExt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,53 +3,31 @@ module ManifoldsBasePlotsExt
using ManifoldsBase
using Plots
using Printf: @sprintf
import ManifoldsBase: plot_slope

function ManifoldsBase.plot_slope(
x,
y;
slope = 2,
line_base = 0,
a = 0,
b = 2.0,
i = 1,
j = length(x),
::Val{:Plots}, x, y;
slope = 2, line_base = 0, a = 0, b = 2.0, i = 1, j = length(x),
)
fig = plot(
x,
y;
xaxis = :log,
yaxis = :log,
label = "\$E(t)\$",
linewidth = 3,
legend = :topleft,
color = :lightblue,
x, y; xaxis = :log, yaxis = :log, label = "\$E(t)\$",
linewidth = 3, legend = :topleft, color = :lightblue,
)
s_line = [exp10(line_base + t * slope) for t in log10.(x)]
plot!(
fig,
x,
s_line;
label = "slope s=$slope",
linestyle = :dash,
color = :black,
linewidth = 2,
fig, x, s_line; label = "slope s=$slope",
linestyle = :dash, color = :black, linewidth = 2,
)
if (i != 0) && (j != 0)
best_line = [exp10(a + t * b) for t in log10.(x[i:j])]
plot!(
fig,
x[i:j],
best_line;
fig, x[i:j], best_line;
label = "best slope $(@sprintf("%.4f", b))",
color = :blue,
linestyle = :dot,
linewidth = 2,
color = :blue, linestyle = :dot, linewidth = 2,
)
end
return fig
end
function ManifoldsBase.plot_check_geodesic(T, N, e_norm, e_pt, e_alpha)
function ManifoldsBase.plot_check_geodesic(::Val{:Plots}, T, N, e_norm, e_pt, e_alpha)
fig = plot(
T[1:(N - 1)], e_norm;
# Deviation from constant speed: |‖Xᵢ‖ − mean‖X‖|
Expand Down
53 changes: 50 additions & 3 deletions src/ManifoldsBase.jl
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
@doc """
🏔️ ManifoldsBase.jl: An interface for manifolds in Julia

* 📚 Documentation: [juliamanifolds.github.io/ManifoldsBase.jl/](https://juliamanifolds.github.io/ManifoldsBase.jl/)
* 📦 Repository: [github.com/JuliaManifolds/ManifoldsBase.jl](https://github.com/JuliaManifolds/ManifoldsBase.jl)
* 🎯 Issues: [github.com/JuliaManifolds/ManifoldsBase.jl/issues](https://github.com/JuliaManifolds/ManifoldsBase.jl/issues)
"""
module ManifoldsBase

import Base:
Expand All @@ -24,9 +31,11 @@ import Random: rand, rand!

using LinearAlgebra
using Markdown: @doc_str
using Preferences
using Printf: @sprintf
using Random


include("maintypes.jl")
include("numbers.jl")
include("Fiber.jl")
Expand Down Expand Up @@ -1219,6 +1228,41 @@ function zero_vector(M::AbstractManifold, p)
zero_vector!(M, X, p)
return X
end

#
#
# Internal function to set plotting backend

"""
set_plotting_backend!(backend::String; only_fallback = false)

Set the plotting backend to `backend`.
Currently supported: `"Plots"` and `"Makie"`.

An empty string resets to the default to use the last loaded one.
"""
function set_plotting_backend!(e::String)
(length(e) == 0) && (return Preferences.@delete_preferences!("PlottingBackend"))
# for the nonpersistent / fallback case, only set the value in the package
return Preferences.@set_preferences!("PlottingBackend" => e)
end

"""
get_plotting_backend()

Return the current plotting backend.
If none was set by the user, the last loaded one is returned. If none was loaded `nothing` is returned
"""
function get_plotting_backend()
def = nothing
# Choose a default – if both are loaded this order makes it Makie
!isnothing(Base.get_extension(ManifoldsBase, :ManifoldsBasePlotsExt)) && (def = "Plots")
!isnothing(Base.get_extension(ManifoldsBase, :ManifoldsBaseMakieExt)) && (def = "Makie")
# unless the user has set one
return Preferences.@load_preference("PlottingBackend", def)
end


include("errors.jl")
include("parallel_transport.jl")
include("vector_transport.jl")
Expand Down Expand Up @@ -1253,17 +1297,20 @@ function __init__()
#
return @static if isdefined(Base.Experimental, :register_error_hint) # COV_EXCL_LINE
Base.Experimental.register_error_hint(MethodError) do io, exc, argtypes, kwargs
if exc.f === plot_slope
if (exc.f === plot_slope) || (exc.f === plot_check_geodesic)
print(
io,
"""

`plot_slope` has to be implemented using your favourite plotting package.
A default is available when Plots.jl is added to the current environment.
`$(exc.f)` has to be implemented using your favourite plotting package.
A default is available when either `Plots.jl` or `Makie.jl` is loaded..
To then get the plotting functionality activated, do
""",
)
printstyled(io, "`using Plots`"; color = :cyan)
print(io, " or ")
printstyled(io, "`using CairoMakie`"; color = :cyan)
print(io, " or your favourite other Makie backend. You might have to add these to your environment first as well.")
end
if exc.f === find_best_slope_window
print(
Expand Down
Loading
Loading