Skip to content

Commit cade4f2

Browse files
committed
Working version, but unnecessarily overloads SciMLBase.@recipe
modified: Project.toml modified: src/MechGlueDiffEqBase.jl modified: test/Manifest.toml modified: test/Project.toml modified: test/runtests.jl
1 parent 9efe868 commit cade4f2

File tree

5 files changed

+116
-26
lines changed

5 files changed

+116
-26
lines changed

Project.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ version = "0.1.31"
55

66
[deps]
77
DiffEqBase = "2b5f629d-d688-5b77-993f-72d75c75574e"
8+
MechGluePlots = "03a24088-0a82-4850-846f-2cad5d056ae1"
89
MechanicalUnits = "e6be9192-89dc-11e9-36e6-5dbcb28f419e"
910
RecipesBase = "3cdcf5f2-1ef4-517c-9805-6587b60abb01"
1011
SciMLBase = "0bca4576-84f4-4d90-8ffe-ffa030f20462"

src/MechGlueDiffEqBase.jl

Lines changed: 97 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,18 @@
11
module MechGlueDiffEqBase
2-
import Unitfu: AbstractQuantity, Quantity
2+
import Unitfu: AbstractQuantity, Quantity, ustrip
33
import DiffEqBase: value, ODE_DEFAULT_NORM, UNITLESS_ABS2
4+
export value, ODE_DEFAULT_NORM, UNITLESS_ABS2, Unitfu, AbstractQuantity, Quantity
5+
6+
7+
import RecipesBase
8+
import RecipesBase.@recipe
49
import SciMLBase
510
import SciMLBase: AbstractTimeseriesSolution, RecipesBase
611
import SciMLBase: AbstractDiscreteProblem, AbstractRODESolution, SensitivityInterpolation
7-
import RecipesBase.@recipe
8-
export value, ODE_DEFAULT_NORM, UNITLESS_ABS2, Unitfu
12+
import SciMLBase: getsyms, interpret_vars, cleansyms
13+
import SciMLBase: diffeq_to_arrays, issymbollike, getindepsym_defaultt
14+
import SciMLBase: DEFAULT_PLOT_FUNC
15+
916

1017
function value(x::Type{AbstractQuantity{T,D,U}}) where {T,D,U}
1118
T
@@ -26,7 +33,8 @@ end
2633
real(abs2(x)/oneunit(x)*oneunit(x))
2734
end
2835

29-
36+
# This recipe is copied from SciMLBase, and only the signature is adopted
37+
# for use with unitful solutions. It can perhaps be deleted now, and the link to RecipesBase be deleted.
3038
@recipe function f(sol::AbstractTimeseriesSolution{T, N, A};
3139
plot_analytic=false,
3240
denseplot = (sol.dense ||
@@ -41,13 +49,91 @@ end
4149
1000*sol.tslocation),
4250
tspan = nothing, axis_safety = 0.1,
4351
vars=nothing) where {T<:Quantity, N, A<:Array{<:Quantity}}
44-
45-
print("----------------------------------MechGlueDiffEqBase")
46-
return Unifu.ustrip(sol.u), Unifu.ustrip(sol.t)
52+
syms = getsyms(sol)
53+
int_vars = interpret_vars(vars,sol,syms)
54+
strs = cleansyms(syms)
55+
56+
tscale = get(plotattributes, :xscale, :identity)
57+
plot_vecs,labels = diffeq_to_arrays(sol,plot_analytic,denseplot,
58+
plotdensity,tspan,axis_safety,
59+
vars,int_vars,tscale,strs)
60+
61+
tdir = sign(sol.t[end]-sol.t[1])
62+
xflip --> tdir < 0
63+
seriestype --> :path
64+
65+
# Special case labels when vars = (:x,:y,:z) or (:x) or [:x,:y] ...
66+
if typeof(vars) <: Tuple && (issymbollike(vars[1]) && issymbollike(vars[2]))
67+
xguide --> issymbollike(int_vars[1][2]) ? Symbol(int_vars[1][2]) : strs[int_vars[1][2]]
68+
yguide --> issymbollike(int_vars[1][3]) ? Symbol(int_vars[1][3]) : strs[int_vars[1][3]]
69+
if length(vars) > 2
70+
zguide --> issymbollike(int_vars[1][4]) ? Symbol(int_vars[1][4]) : strs[int_vars[1][4]]
71+
end
72+
end
73+
74+
if (!any(issymbollike,getindex.(int_vars,1)) && getindex.(int_vars,1) == zeros(length(int_vars))) ||
75+
(!any(issymbollike,getindex.(int_vars,2)) && getindex.(int_vars,2) == zeros(length(int_vars))) ||
76+
all(t->Symbol(t)==getindepsym_defaultt(sol),getindex.(int_vars,1)) || all(t->Symbol(t)==getindepsym_defaultt(sol),getindex.(int_vars,2))
77+
xguide --> "$(getindepsym_defaultt(sol))"
78+
end
79+
if length(int_vars[1]) >= 3 && ((!any(issymbollike,getindex.(int_vars,3)) && getindex.(int_vars,3) == zeros(length(int_vars))) ||
80+
all(t->Symbol(t)==getindepsym_defaultt(sol),getindex.(int_vars,3)))
81+
yguide --> "$(getindepsym_defaultt(sol))"
82+
end
83+
if length(int_vars[1]) >= 4 && ((!any(issymbollike,getindex.(int_vars,4)) && getindex.(int_vars,4) == zeros(length(int_vars))) ||
84+
all(t->Symbol(t)==getindepsym_defaultt(sol),getindex.(int_vars,4)))
85+
zguide --> "$(getindepsym_defaultt(sol))"
86+
end
87+
88+
if (!any(issymbollike,getindex.(int_vars,2)) && getindex.(int_vars,2) == zeros(length(int_vars))) ||
89+
all(t->Symbol(t)==getindepsym_defaultt(sol),getindex.(int_vars,2))
90+
if tspan === nothing
91+
if tdir > 0
92+
xlims --> (sol.t[1],sol.t[end])
93+
else
94+
xlims --> (sol.t[end],sol.t[1])
95+
end
96+
else
97+
xlims --> (tspan[1],tspan[end])
98+
end
99+
else
100+
mins = minimum(sol[int_vars[1][2],:])
101+
maxs = maximum(sol[int_vars[1][2],:])
102+
for iv in int_vars
103+
mins = min(mins,minimum(sol[iv[2],:]))
104+
maxs = max(maxs,maximum(sol[iv[2],:]))
105+
end
106+
xlims --> ((1-sign(mins)*axis_safety)*mins,(1+sign(maxs)*axis_safety)*maxs)
107+
end
108+
109+
# Analytical solutions do not save enough information to have a good idea
110+
# of the axis ahead of time
111+
# Only set axis for animations
112+
if sol.tslocation != 0 && !(typeof(sol) <: AbstractAnalyticalSolution)
113+
if all(getindex.(int_vars,1) .== DEFAULT_PLOT_FUNC)
114+
mins = minimum(sol[int_vars[1][3],:])
115+
maxs = maximum(sol[int_vars[1][3],:])
116+
for iv in int_vars
117+
mins = min(mins,minimum(sol[iv[3],:]))
118+
maxs = max(maxs,maximum(sol[iv[3],:]))
119+
end
120+
ylims --> ((1-sign(mins)*axis_safety)*mins,(1+sign(maxs)*axis_safety)*maxs)
121+
122+
if length(int_vars[1]) >= 4
123+
mins = minimum(sol[int_vars[1][4],:])
124+
maxs = maximum(sol[int_vars[1][4],:])
125+
for iv in int_vars
126+
mins = min(mins,minimum(sol[iv[4],:]))
127+
maxs = max(mins,maximum(sol[iv[4],:]))
128+
end
129+
zlims --> ((1-sign(mins)*axis_safety)*mins,(1+sign(maxs)*axis_safety)*maxs)
130+
end
131+
end
132+
end
133+
134+
label --> reshape(labels,1,length(labels))
135+
println("----------------------------------MechGlueDiffEqBase")
136+
(plot_vecs...,)
47137
end
48-
# T = Quantity{Float64, ᴸ∙ ᴹ∙ ᵀ⁻², Unitfu.FreeUnits{(N,), ᴸ∙ ᴹ∙ ᵀ⁻², nothing}}
49-
# N = 1
50-
# A = Vector{Quantity{Float64, ᴸ∙ ᴹ∙ ᵀ⁻², Unitfu.FreeUnits{(N,), ᴸ∙ ᴹ∙ ᵀ⁻², nothing}}}
51-
52138

53139
end

test/Manifest.toml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -613,11 +613,17 @@ uuid = "442fdcdd-2543-5da2-b0f3-8c86c306513e"
613613
version = "0.3.1"
614614

615615
[[MechGlueDiffEqBase]]
616-
deps = ["DiffEqBase", "MechanicalUnits", "RecipesBase", "SciMLBase", "Unitfu"]
616+
deps = ["DiffEqBase", "MechGluePlots", "MechanicalUnits", "RecipesBase", "SciMLBase", "Unitfu"]
617617
path = "C:\\Users\\frohu_h4g8g6y\\.julia\\dev\\MechGlueDiffEqBase"
618618
uuid = "2532746b-52b5-4539-9431-8bb183ab067f"
619619
version = "0.1.31"
620620

621+
[[MechGluePlots]]
622+
deps = ["Plots", "RecipesBase", "Unitfu"]
623+
git-tree-sha1 = "2b4328a7d4eb2ee41cc060df6cddd9f1a0b1de23"
624+
uuid = "03a24088-0a82-4850-846f-2cad5d056ae1"
625+
version = "0.2.1"
626+
621627
[[MechanicalUnits]]
622628
deps = ["Base64", "Distributed", "InteractiveUtils", "Libdl", "LinearAlgebra", "Logging", "Markdown", "Random", "Serialization", "Sockets", "Test", "Unitfu"]
623629
git-tree-sha1 = "0e0eca9fbd0d9c575d8cd106979c350bf0fe057b"

test/Project.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
[deps]
22
DifferentialEquations = "0c46a032-eb83-5123-abaf-570d42b7fbaa"
33
MechGlueDiffEqBase = "2532746b-52b5-4539-9431-8bb183ab067f"
4+
MechGluePlots = "03a24088-0a82-4850-846f-2cad5d056ae1"
45
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
56
SciMLBase = "0bca4576-84f4-4d90-8ffe-ffa030f20462"

test/runtests.jl

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using MechGlueDiffEqBase
2-
import MechanicalUnits: @import_expand, Quantity, Time, Force, , Quantity
2+
using MechGluePlots
3+
import MechanicalUnits: @import_expand, Quantity, Time, Force,
34
import Unitfu.AbstractQuantity
45
import DifferentialEquations
56
import DifferentialEquations: SciMLBase, solve, ODEProblem, Tsit5
@@ -8,7 +9,8 @@ import SciMLBase: AbstractTimeseriesSolution, RecipesBase
89
import SciMLBase: AbstractDiscreteProblem, AbstractRODESolution, SensitivityInterpolation
910
using Test
1011
import Plots.plot
11-
@import_expand(N, s)
12+
13+
@import_expand(N, s, m)
1214
@testset "ODE" begin
1315
f = (y, p, t) -> 0.5y / 3.0s # The derivative, yeah
1416
u0 = 1.5N
@@ -20,7 +22,7 @@ import Plots.plot
2022
@test sol.u isa Vector{<:Force}
2123
end
2224

23-
@testset "Plot ODE quantity" begin
25+
#@testset "Plot ODE quantity" begin
2426
SciMLBase.RecipesBase.debug(true)
2527
f1 = (y, p, t) -> -1.5y / 0.3s # The derivative, yeah
2628
u0 = 1.5N
@@ -29,17 +31,11 @@ end
2931
solve(prob, Tsit5())
3032
sol = solve(prob)
3133
@test sol isa AbstractTimeseriesSolution{T, N, A} where {T, N, A}
32-
@test sol isa AbstractTimeseriesSolution{T, N, A} where {T<:AbstractQuantity, N, A}
33-
@test sol isa AbstractTimeseriesSolution{T, N, A} where {T<:AbstractQuantity, N, A<:AbstractArray{<:AbstractQuantity}}
34+
@test sol isa AbstractTimeseriesSolution{T, N, A} where {T<:Quantity, N, A}
3435
@test sol isa AbstractTimeseriesSolution{T, N, A} where {T<:Quantity, N, A<:Array{<:Quantity}}
36+
# Here, we only test this part of the dispatch mechanism.
37+
# This is intended to work with MechGluePlots also loaded.
38+
# See other tests in MechGluecode.
3539
plot(sol)
36-
# TODO implement in MechGlueDiffEqBase
37-
# the recipe found in SciMLBase/solutions/solution_interface.jl:151
38-
# Type to dispatch on:
39-
# AbstractTimeseriesSolution{T, N, A}) where {T, N, A}
40-
# T = Quantity{Float64, ᴸ∙ ᴹ∙ ᵀ⁻², Unitfu.FreeUnits{(N,), ᴸ∙ ᴹ∙ ᵀ⁻², nothing}}
41-
# N = 1
42-
# A = Vector{Quantity{Float64, ᴸ∙ ᴹ∙ ᵀ⁻², Unitfu.FreeUnits{(N,), ᴸ∙ ᴹ∙ ᵀ⁻², nothing}}}
43-
44-
end
40+
#end
4541

0 commit comments

Comments
 (0)