From c88f660b428b66ba1c6e3f1baf5a7d2d613a3d00 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 28 Jul 2025 17:05:29 -0400 Subject: [PATCH] Fix Makie recipe to support 3D plots with automatic LScene detection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit adds `preferred_axis_type` methods for AbstractTimeseriesSolution, DEIntegrator, and AbstractEnsembleSolution that automatically detect when 3D plotting is requested (idxs=(1,2,3)) and return LScene as the preferred axis type instead of the default Axis. This fixes issue #947 where 3D plots failed because Makie defaulted to 2D Axis instead of using LScene for 3D visualizations. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- ext/SciMLBaseMakieExt.jl | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/ext/SciMLBaseMakieExt.jl b/ext/SciMLBaseMakieExt.jl index 0071ee47c..291aa2d2b 100644 --- a/ext/SciMLBaseMakieExt.jl +++ b/ext/SciMLBaseMakieExt.jl @@ -23,6 +23,19 @@ function ensure_plottrait(PT::Type, arg, desired_plottrait_type::Type) end end +# Define preferred axis type based on the idxs parameter +function Makie.preferred_axis_type(plot::Plot{<:Tuple{<:SciMLBase.AbstractTimeseriesSolution}}) + if haskey(plot, :idxs) || haskey(plot, :vars) + idxs = haskey(plot, :idxs) ? plot[:idxs][] : (haskey(plot, :vars) ? plot[:vars][] : nothing) + if idxs isa Tuple && length(idxs) == 3 + return Makie.LScene + elseif idxs isa AbstractArray && length(idxs) == 3 + return Makie.LScene + end + end + return Makie.Axis +end + # ## `AbstractTimeseriesSolution` recipe # First, we define the standard plot type for timeseries solutions. @@ -138,6 +151,19 @@ end Makie.plottype(integrator::SciMLBase.DEIntegrator) = Makie.Lines +# Define preferred axis type for integrator plots +function Makie.preferred_axis_type(plot::Plot{<:Tuple{<:SciMLBase.DEIntegrator}}) + if haskey(plot, :idxs) || haskey(plot, :vars) + idxs = haskey(plot, :idxs) ? plot[:idxs][] : (haskey(plot, :vars) ? plot[:vars][] : nothing) + if idxs isa Tuple && length(idxs) == 3 + return Makie.LScene + elseif idxs isa AbstractArray && length(idxs) == 3 + return Makie.LScene + end + end + return Makie.Axis +end + function Makie.used_attributes(::Type{<:Plot}, integrator::SciMLBase.DEIntegrator) (:plot_analytic, :denseplot, :plotdensity, :vars, :idxs) end @@ -273,6 +299,19 @@ end # Again, we first define the "ideal" plot type for ensemble solutions. Makie.plottype(sol::SciMLBase.AbstractEnsembleSolution) = Makie.Lines +# Define preferred axis type for ensemble plots +function Makie.preferred_axis_type(plot::Plot{<:Tuple{<:SciMLBase.AbstractEnsembleSolution}}) + if haskey(plot, :idxs) || haskey(plot, :vars) + idxs = haskey(plot, :idxs) ? plot[:idxs][] : (haskey(plot, :vars) ? plot[:vars][] : nothing) + if idxs isa Tuple && length(idxs) == 3 + return Makie.LScene + elseif idxs isa AbstractArray && length(idxs) == 3 + return Makie.LScene + end + end + return Makie.Axis +end + # We also define the attributes that are used by the ensemble solution recipe: function Makie.used_attributes(::Type{<:Plot}, sol::SciMLBase.AbstractEnsembleSolution) (:trajectories,