Skip to content

Commit a25e016

Browse files
authored
Merge branch 'main' into examples_cp
2 parents 198d7e3 + 3191a39 commit a25e016

2 files changed

Lines changed: 107 additions & 1 deletion

File tree

ext/VortexStepMethodControlPlotsExt.jl

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ function VortexStepMethod.save_plot(fig, save_path, title; data_type=".pdf")
8282
end
8383

8484
"""
85-
show_plot(fig; dpi=130)
85+
show_plot(fig::plt.Figure; dpi=130)
8686
8787
Display a plot at specified DPI.
8888
@@ -587,6 +587,37 @@ function generate_polar_data(
587587
return polar_data, reynolds_number[1]
588588
end
589589

590+
function _extract_literature_polar_data(raw_data, path)
591+
table, header = if raw_data isa Tuple
592+
# readdlm(...; header=true) returns (data, header)
593+
raw_table, raw_header = raw_data
594+
raw_table, lowercase.(strip.(string.(vec(raw_header))))
595+
else
596+
# Header is in first row when a single matrix is returned
597+
raw_data[2:end, :], lowercase.(strip.(string.(raw_data[1, :])))
598+
end
599+
600+
# Find column indices for alpha, CL, CD, CS (case-insensitive, allow common variants)
601+
alpha_idx = findfirst(x -> occursin("alpha", x) || x == "aoa", header)
602+
cl_idx = findfirst(x -> occursin("cl", x), header)
603+
cd_idx = findfirst(x -> occursin("cd", x), header)
604+
cs_idx = findfirst(x -> occursin("cs", x), header)
605+
606+
(isnothing(alpha_idx) || isnothing(cl_idx) || isnothing(cd_idx)) &&
607+
throw(ArgumentError("Literature CSV must contain alpha/aoa, cl and cd columns: $path"))
608+
609+
# Fallback: if CS not found, fill with zeros
610+
cs_col = cs_idx === nothing ? zeros(size(table, 1)) : table[:, cs_idx]
611+
612+
# Return as [alpha, CL, CD, CS]
613+
return [
614+
table[:, alpha_idx],
615+
table[:, cl_idx],
616+
table[:, cd_idx],
617+
cs_col
618+
]
619+
end
620+
590621
"""
591622
plot_polars(solver_list, body_aero_list, label_list;
592623
literature_path_list=String[],
@@ -686,6 +717,7 @@ function VortexStepMethod.plot_polars(
686717
table[:, cd_idx],
687718
cs_col
688719
])
720+
push!(polar_data_list, _extract_literature_polar_data(raw_data, path))
689721
end
690722
end
691723

test/plotting/test_plotting.jl

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
backend = if "plot-controlplots" in ARGS
22
using ControlPlots
3+
import ControlPlots: plt
34
"ControlPlots"
45
else
56
using CairoMakie
@@ -271,6 +272,79 @@ end
271272
finally
272273
safe_rm(literature_csv)
273274
end
275+
fig_dpi = plt.figure()
276+
default_dpi = fig_dpi.get_dpi()
277+
@test default_dpi != 173
278+
279+
show_plot(fig_dpi; dpi=173)
280+
@test fig_dpi.get_dpi() == 173
281+
282+
# Also verify the default keyword value is applied.
283+
show_plot(fig_dpi)
284+
@test fig_dpi.get_dpi() == 130
285+
plt.close(fig_dpi)
286+
287+
ext = Base.get_extension(VortexStepMethod, :VortexStepMethodControlPlotsExt)
288+
@test ext !== nothing
289+
290+
# Unit-test tuple parsing branch (e.g. readdlm(...; header=true) shape).
291+
tuple_table = [0.0 0.10 0.010; 5.0 0.20 0.020]
292+
tuple_header = [" AoA " "CL" "CD"]
293+
tuple_pd = ext._extract_literature_polar_data((tuple_table, tuple_header), "tuple.csv")
294+
@test tuple_pd[1] == tuple_table[:, 1]
295+
@test tuple_pd[2] == tuple_table[:, 2]
296+
@test tuple_pd[3] == tuple_table[:, 3]
297+
@test tuple_pd[4] == zeros(size(tuple_table, 1))
298+
299+
# Unit-test matrix parsing branch (header in first row + explicit CS column).
300+
matrix_data = Any[
301+
"alpha" "cl" "cd" "cs";
302+
0.0 0.11 0.011 0.001;
303+
4.0 0.21 0.021 0.002
304+
]
305+
matrix_pd = ext._extract_literature_polar_data(matrix_data, "matrix.csv")
306+
@test Float64.(matrix_pd[1]) == [0.0, 4.0]
307+
@test Float64.(matrix_pd[2]) == [0.11, 0.21]
308+
@test Float64.(matrix_pd[3]) == [0.011, 0.021]
309+
@test Float64.(matrix_pd[4]) == [0.001, 0.002]
310+
311+
# Missing required columns should throw a clear ArgumentError.
312+
bad_data = Any[
313+
"aoa" "cl" "cs";
314+
0.0 0.1 0.0
315+
]
316+
@test_throws ArgumentError ext._extract_literature_polar_data(bad_data, "bad.csv")
317+
318+
# Integration: literature CSV with AoA alias and no CS should still plot.
319+
lit_no_cs_path = tempname() * "_lit_no_cs.csv"
320+
open(lit_no_cs_path, "w") do io_no_cs
321+
write(io_no_cs, "aoa,cl,cd\n0.0,0.10,0.010\n5.0,0.20,0.020\n")
322+
end
323+
fig_lit_no_cs = plot_polars(
324+
Any[],
325+
Any[],
326+
["Literature no CS"];
327+
literature_path_list=[lit_no_cs_path],
328+
is_save=false,
329+
is_show=false
330+
)
331+
@test fig_lit_no_cs !== nothing
332+
safe_rm(lit_no_cs_path)
333+
334+
# Integration: missing CD column should fail.
335+
lit_bad_path = tempname() * "_lit_bad.csv"
336+
open(lit_bad_path, "w") do io_bad
337+
write(io_bad, "alpha,cl\n0.0,0.10\n5.0,0.20\n")
338+
end
339+
@test_throws ArgumentError plot_polars(
340+
Any[],
341+
Any[],
342+
["Literature bad"];
343+
literature_path_list=[lit_bad_path],
344+
is_save=false,
345+
is_show=false
346+
)
347+
safe_rm(lit_bad_path)
274348
end
275349
end
276350
nothing

0 commit comments

Comments
 (0)