Skip to content

Commit dd15a6b

Browse files
committed
add mutating versions
1 parent b49025a commit dd15a6b

File tree

3 files changed

+86
-183
lines changed

3 files changed

+86
-183
lines changed

lib/ControlSystemsBase/ext/ControlSystemsBaseMakieExt.jl

Lines changed: 53 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,14 @@ function get_yscale_transform()
2323
end
2424

2525
# ====== PZMap (Pole-Zero Map) ======
26-
function CSMakie.pzmap(systems::Union{LTISystem, AbstractVector{<:LTISystem}};
26+
function CSMakie.pzmap(args...; kwargs...)
27+
fig = Figure()
28+
CSMakie.pzmap!(fig, args...; kwargs...)
29+
end
30+
function CSMakie.pzmap!(fig, systems::Union{LTISystem, AbstractVector{<:LTISystem}};
2731
hz=false, kwargs...)
2832
systems_vec = systems isa AbstractVector ? systems : [systems]
2933

30-
fig = Figure()
3134
ax = Axis(fig[1,1], aspect = DataAspect(),
3235
title = "Pole-zero map",
3336
xlabel = hz ? "Real [Hz]" : "Real",
@@ -70,48 +73,13 @@ function CSMakie.pzmap(systems::Union{LTISystem, AbstractVector{<:LTISystem}};
7073
return fig
7174
end
7275

73-
function CSMakie.pzmap!(ax::Axis, systems::Union{LTISystem, AbstractVector{<:LTISystem}};
74-
hz=false, kwargs...)
75-
systems_vec = systems isa AbstractVector ? systems : [systems]
76-
77-
# Add grid at zero
78-
vlines!(ax, 0, color=:gray, alpha=0.3, linewidth=0.5)
79-
hlines!(ax, 0, color=:gray, alpha=0.3, linewidth=0.5)
80-
81-
scale_factor = hz ? 1/(2π) : 1
82-
83-
for (i, system) in enumerate(systems_vec)
84-
p = poles(system) .* scale_factor
85-
z = tzeros(system) .* scale_factor
86-
87-
# Plot zeros as circles
88-
if !isempty(z)
89-
scatter!(ax, real(z), imag(z),
90-
marker=:circle, markersize=15,
91-
color=(:transparent, 0.5), strokewidth=2,
92-
strokecolor=Cycled(i))
93-
end
94-
95-
# Plot poles as x's
96-
if !isempty(p)
97-
scatter!(ax, real(p), imag(p),
98-
marker=:xcross, markersize=15,
99-
color=Cycled(i))
100-
end
101-
102-
# Add unit circle for discrete systems
103-
if isdiscrete(system) && i == 1 # Only draw once
104-
θ = range(0, 2π, length=100)
105-
circle_scale = scale_factor
106-
lines!(ax, circle_scale .* cos.(θ), circle_scale .* sin.(θ),
107-
color=:gray, linestyle=:dash, alpha=0.5)
108-
end
109-
end
110-
111-
return ax
112-
end
11376

114-
function CSMakie.bodeplot(systems::Union{LTISystem, AbstractVector{<:LTISystem}},
77+
78+
function CSMakie.bodeplot(args...; kwargs...)
79+
fig = Figure()
80+
CSMakie.bodeplot!(fig, args...; kwargs...)
81+
end
82+
function CSMakie.bodeplot!(fig, systems::Union{LTISystem, AbstractVector{<:LTISystem}},
11583
w=nothing; plotphase=true, unwrap=true, hz=false,
11684
balance=true, adjust_phase_start=true, adaptive=true, kwargs...)
11785
systems_vec = systems isa AbstractVector ? systems : [systems]
@@ -121,7 +89,6 @@ function CSMakie.bodeplot(systems::Union{LTISystem, AbstractVector{<:LTISystem}}
12189
ws = (hz ? 1/(2π) : 1) .* w
12290
ny, nu = size(systems[1])
12391

124-
fig = Figure()
12592
gl = GridLayout(fig[1, 1])
12693

12794
# Create axes grid
@@ -218,7 +185,11 @@ function CSMakie.bodeplot(systems::Union{LTISystem, AbstractVector{<:LTISystem}}
218185
return fig
219186
end
220187

221-
function CSMakie.nyquistplot(systems::Union{LTISystem, AbstractVector{<:LTISystem}},
188+
function CSMakie.nyquistplot(args...; kwargs...)
189+
fig = Figure()
190+
CSMakie.nyquistplot!(fig, args...; kwargs...)
191+
end
192+
function CSMakie.nyquistplot!(fig, systems::Union{LTISystem, AbstractVector{<:LTISystem}},
222193
w=nothing; Ms_circles=Float64[], Mt_circles=Float64[],
223194
unit_circle=false, hz=false, critical_point=-1,
224195
balance=true, adaptive=true, kwargs...)
@@ -227,8 +198,7 @@ function CSMakie.nyquistplot(systems::Union{LTISystem, AbstractVector{<:LTISyste
227198
_processfreqplot(Val{:nyquist}(), systems_vec, w; adaptive)
228199

229200
ny, nu = size(systems[1])
230-
231-
fig = Figure()
201+
232202
gl = GridLayout(fig[1, 1])
233203

234204
# Create axes grid
@@ -307,15 +277,18 @@ function CSMakie.nyquistplot(systems::Union{LTISystem, AbstractVector{<:LTISyste
307277
return fig
308278
end
309279

310-
function CSMakie.sigmaplot(systems::Union{LTISystem, AbstractVector{<:LTISystem}},
280+
function CSMakie.sigmaplot(args...; kwargs...)
281+
fig = Figure()
282+
CSMakie.sigmaplot!(fig, args...; kwargs...)
283+
end
284+
function CSMakie.sigmaplot!(fig, systems::Union{LTISystem, AbstractVector{<:LTISystem}},
311285
w=nothing; hz=false, balance=true, extrema=false, kwargs...)
312286
systems_vec = systems isa AbstractVector ? systems : [systems]
313287
systems, w = isnothing(w) ? _processfreqplot(Val{:sigma}(), systems_vec) :
314288
_processfreqplot(Val{:sigma}(), systems_vec, w)
315289

316290
ws = (hz ? 1/(2π) : 1) .* w
317291

318-
fig = Figure()
319292
ax = Axis(fig[1,1],
320293
xscale = log10,
321294
yscale = get_yscale_transform(),
@@ -342,7 +315,11 @@ function CSMakie.sigmaplot(systems::Union{LTISystem, AbstractVector{<:LTISystem}
342315
return fig
343316
end
344317

345-
function CSMakie.marginplot(systems::Union{LTISystem, AbstractVector{<:LTISystem}},
318+
function CSMakie.marginplot(args...; kwargs...)
319+
fig = Figure()
320+
CSMakie.marginplot!(fig, args...; kwargs...)
321+
end
322+
function CSMakie.marginplot!(fig, systems::Union{LTISystem, AbstractVector{<:LTISystem}},
346323
w=nothing; plotphase=true, hz=false, balance=true,
347324
adjust_phase_start=true, adaptive=true, kwargs...)
348325
systems_vec = systems isa AbstractVector ? systems : [systems]
@@ -352,7 +329,6 @@ function CSMakie.marginplot(systems::Union{LTISystem, AbstractVector{<:LTISystem
352329
ws = (hz ? 1/(2π) : 1) .* w
353330
ny, nu = size(systems[1])
354331

355-
fig = Figure()
356332
gl = GridLayout(fig[1, 1])
357333

358334
# Create axes grid
@@ -489,14 +465,17 @@ function CSMakie.marginplot(systems::Union{LTISystem, AbstractVector{<:LTISystem
489465
return fig
490466
end
491467

492-
function CSMakie.rlocusplot(P::LTISystem, K=500; output=false, kwargs...)
468+
function CSMakie.rlocusplot(args...; kwargs...)
469+
fig = Figure()
470+
CSMakie.rlocusplot!(fig, args...; kwargs...)
471+
end
472+
function CSMakie.rlocusplot!(fig, P::LTISystem, K=500; output=false, kwargs...)
493473
# Compute root locus
494474
result = rlocus(P, K; output=output)
495475
roots, Z, K_vals = result.roots, result.Z, result.K
496476

497477
array_K = eltype(K_vals) <: AbstractArray
498478

499-
fig = Figure()
500479
ax = Axis(fig[1,1],
501480
aspect = DataAspect(),
502481
title = "Root Locus",
@@ -538,15 +517,18 @@ function CSMakie.rlocusplot(P::LTISystem, K=500; output=false, kwargs...)
538517
return fig
539518
end
540519

541-
function CSMakie.rgaplot(systems::Union{LTISystem, AbstractVector{<:LTISystem}},
520+
function CSMakie.rgaplot(args...; kwargs...)
521+
fig = Figure()
522+
CSMakie.rgaplot!(fig, args...; kwargs...)
523+
end
524+
function CSMakie.rgaplot!(fig, systems::Union{LTISystem, AbstractVector{<:LTISystem}},
542525
w=nothing; hz=false, balance=true, kwargs...)
543526
systems_vec = systems isa AbstractVector ? systems : [systems]
544527
systems, w = isnothing(w) ? _processfreqplot(Val{:sigma}(), systems_vec) :
545528
_processfreqplot(Val{:sigma}(), systems_vec, w)
546529

547530
ws = (hz ? 1/(2π) : 1) .* w
548531

549-
fig = Figure()
550532
ax = Axis(fig[1,1],
551533
xscale = log10,
552534
title = "RGA Plot",
@@ -571,11 +553,14 @@ function CSMakie.rgaplot(systems::Union{LTISystem, AbstractVector{<:LTISystem}},
571553
end
572554

573555
# ====== LeadLinkCurve ======
574-
function CSMakie.leadlinkcurve(start=1; kwargs...)
556+
function CSMakie.leadlinkcurve(args...; kwargs...)
557+
fig = Figure()
558+
CSMakie.leadlinkcurve!(fig, args...; kwargs...)
559+
end
560+
function CSMakie.leadlinkcurve!(fig, start=1; kwargs...)
575561
N = range(start, stop=10, length=50)
576562
dph = map(Ni -> 180/π*atan(sqrt(Ni)) - atan(1/sqrt(Ni)), N)
577563

578-
fig = Figure()
579564
ax = Axis(fig[1,1],
580565
xlabel = "N",
581566
ylabel = "Phase advance [deg]",
@@ -589,15 +574,18 @@ end
589574
# ====== Nicholsplot ======
590575
# Note: This is a simplified version. The full implementation would require
591576
# porting all the complex grid calculations from the Plots version
592-
function CSMakie.nicholsplot(systems::Union{LTISystem, AbstractVector{<:LTISystem}},
577+
function CSMakie.nicholsplot(args...; kwargs...)
578+
fig = Figure()
579+
CSMakie.nicholsplot!(fig, args...; kwargs...)
580+
end
581+
function CSMakie.nicholsplot!(fig, systems::Union{LTISystem, AbstractVector{<:LTISystem}},
593582
w=nothing; text=true,
594583
Gains=[12, 6, 3, 1, 0.5, -0.5, -1, -3, -6, -10, -20, -40, -60],
595584
pInc=30, kwargs...)
596585
systems_vec = systems isa AbstractVector ? systems : [systems]
597586
systems, w = isnothing(w) ? _processfreqplot(Val{:nyquist}(), systems_vec) :
598587
_processfreqplot(Val{:nyquist}(), systems_vec, w)
599588

600-
fig = Figure()
601589
ax = Axis(fig[1,1],
602590
title = "Nichols Chart",
603591
xlabel = "Phase [deg]",
@@ -621,7 +609,9 @@ function CSMakie.nicholsplot(systems::Union{LTISystem, AbstractVector{<:LTISyste
621609
return fig
622610
end
623611

624-
function Makie.plot(r::SimResult; plotu=false, plotx=false, ploty=true)
612+
Makie.plot(r::SimResult; kwargs...) = Makie.plot!(Figure(), r; kwargs...)
613+
614+
function Makie.plot!(fig, r::SimResult; plotu=false, plotx=false, ploty=true)
625615
ny, nu, nx = r.ny, r.nu, r.nx
626616
t = r.t
627617
n_series = size(r.y, 3)
@@ -632,7 +622,6 @@ function Makie.plot(r::SimResult; plotu=false, plotx=false, ploty=true)
632622
plotx && (nplots += nx)
633623

634624
# Create figure with grid layout
635-
fig = Figure()
636625
gl = GridLayout(fig[1, 1])
637626

638627
plotind = 1
@@ -710,8 +699,9 @@ function Makie.plot(r::SimResult; plotu=false, plotx=false, ploty=true)
710699
return fig
711700
end
712701

713-
function Makie.plot(si::StepInfo)
714-
fig = Figure()
702+
Makie.plot(si::StepInfo; kwargs...) = Makie.plot!(Figure(), si; kwargs...)
703+
704+
function Makie.plot!(fig, si::StepInfo)
715705
ax = Axis(fig[1,1],
716706
xlabel = "Time (s)",
717707
ylabel = "Output",

0 commit comments

Comments
 (0)