From 860850eb702ac4eefe6d4fa8deff7df5b02cecd6 Mon Sep 17 00:00:00 2001 From: 1-Bort-1 <323661610+1-Bort-1@users.noreply.github.com> Date: Wed, 23 Sep 2026 10:55:45 +0200 Subject: [PATCH 1/3] Test that show_title=false keeps plot titles off the figure Co-Authored-By: Claude Opus 5.5 --- test/plotting/test_plotting.jl | 75 ++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/test/plotting/test_plotting.jl b/test/plotting/test_plotting.jl index 6c780c60..974ee8ed 100644 --- a/test/plotting/test_plotting.jl +++ b/test/plotting/test_plotting.jl @@ -25,6 +25,23 @@ using Test const makie_ext = Base.get_extension(VortexStepMethod, :VortexStepMethodMakieExt) +""" + drawn_titles(fig) -> Vector{String} + +Texts of the `Label`s and of the visible `Axis`/`Axis3` titles drawn on `fig`. +""" +function drawn_titles(fig) + titles = String[] + for block in fig.content + if block isa Label + push!(titles, string(block.text[])) + elseif block isa Union{Axis, Axis3} && block.titlevisible[] + push!(titles, string(block.title[])) + end + end + return titles +end + global ram_wing = ram_air_matrix_wing(; n_panels=20, n_sections=4, alpha_range=deg2rad.(-1:1.0:1), delta_range=deg2rad.(-1:1.0:1)) @@ -166,6 +183,38 @@ end ) @test fig isa Figure + @testset "show_title=false hides the title but still names the file" begin + fig = plot_geometry(body_aero, "Hidden geometry"; save_path=save_dir, + is_save=true, is_show=false) + @test "Hidden geometry" in drawn_titles(fig) + fig = plot_geometry(body_aero, "Hidden geometry"; data_type=".png", + save_path=save_dir, is_save=true, is_show=false, show_title=false) + @test isempty(drawn_titles(fig)) + @test isfile(joinpath(save_dir, "Hidden_geometry_top_view.png")) + + distribution_args = ([y_coordinates], [results_vsm], ["VSM"]) + fig = plot_distribution(distribution_args...; title="Hidden distribution", + is_show=false) + @test "Hidden distribution" in drawn_titles(fig) + fig = plot_distribution(distribution_args...; title="Hidden distribution", + data_type=".png", save_path=save_dir, is_save=true, is_show=false, + show_title=false) + @test "Hidden distribution" ∉ drawn_titles(fig) + @test "CL Distribution" in drawn_titles(fig) + @test isfile(joinpath(save_dir, "Hidden_distribution.png")) + + combined_kwargs = (angle_range=range(0, 10, 2), va, is_show=false) + fig = plot_combined_analysis(vsm_solver, body_aero, results_vsm; + title="Hidden combined", combined_kwargs...) + @test "Hidden combined" in drawn_titles(fig) + fig = plot_combined_analysis(vsm_solver, body_aero, results_vsm; + title="Hidden combined", data_type=".png", save_path=save_dir, + is_save=true, show_title=false, combined_kwargs...) + @test "Hidden combined" ∉ drawn_titles(fig) + @test "Wing Geometry" in drawn_titles(fig) + @test isfile(joinpath(save_dir, "Hidden_combined.png")) + end + @testset "round-off CS plots flat, a varying CS keeps its autoscale" begin fig = Figure() ax_noise = Axis(fig[1, 1]) @@ -606,6 +655,32 @@ end end end +@testset "show_title=false hides the airfoil and section polar titles" begin + body_aero, _ = create_body_aero_with_skin() + @test plot_section_polars(body_aero; is_show=false).title == "Section polars" + @test plot_section_polars(body_aero; is_show=false, show_title=false).title == "" + + _, geometry_file = ram_air_matrix_dir(; n_sections=4, + alpha_range=deg2rad.(-1:1.0:1), delta_range=deg2rad.(-1:1.0:1)) + obj_adapter = VortexStepMethod.ObjAdapter + airfoil = first(obj_adapter.airfoils_from_yaml(geometry_file)) + fig, _ = obj_adapter.plot_airfoil_fit(airfoil.x, airfoil.y; title="Hidden fit", + is_show=false) + @test "Hidden fit" in drawn_titles(fig) + fig, _ = obj_adapter.plot_airfoil_fit(airfoil.x, airfoil.y; title="Hidden fit", + is_show=false, show_title=false) + @test drawn_titles(fig) == ["Kulfan Parameters"] + + airfoils_title = "Airfoils: geometry.yaml" + for overlay in (false, true) + fig = obj_adapter.plot_airfoils(geometry_file; overlay, is_show=false) + @test airfoils_title in drawn_titles(fig) + fig = obj_adapter.plot_airfoils(geometry_file; overlay, is_show=false, + show_title=false) + @test airfoils_title ∉ drawn_titles(fig) + end +end + @testset "Audit slices (Makie)" begin # An all-NaN deflected .dat reads as empty; here a header-only file stands in. gen_dir, _ = ram_air_matrix_dir(; n_sections=4, From 13bee19f9eb70dea93530c43ceb8e5fc0b48698d Mon Sep 17 00:00:00 2001 From: 1-Bort-1 <323661610+1-Bort-1@users.noreply.github.com> Date: Wed, 23 Sep 2026 10:57:24 +0200 Subject: [PATCH 2/3] Add show_title to every plot that draws its title plot_geometry (and its saved views), plot_distribution, plot_combined_analysis, plot_section_polars, plot_airfoil_fit and plot_airfoils take show_title=true. With false the title is not drawn; it still names the saved file and window. Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 8 ++++ ext/VortexStepMethodMakieExt.jl | 78 +++++++++++++++++++-------------- src/VortexStepMethod.jl | 4 ++ 3 files changed, 56 insertions(+), 34 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4578e6ad..7f905a24 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## Unreleased + +### Added + +- `plot_geometry`, `plot_distribution`, `plot_combined_analysis`, `plot_section_polars`, + `plot_airfoil_fit` and `plot_airfoils` take `show_title=true`; with `false` the title + is not drawn, and it still names the saved file and the window where it did. + ## VortexStepMethod v6.0.0 2026-09-23 ### Added diff --git a/ext/VortexStepMethodMakieExt.jl b/ext/VortexStepMethodMakieExt.jl index 111e0fcb..551932ba 100644 --- a/ext/VortexStepMethodMakieExt.jl +++ b/ext/VortexStepMethodMakieExt.jl @@ -616,7 +616,7 @@ end """ create_geometry_plot_makie(body_aero::BodyAerodynamics, title, - view_elevation, view_azimuth; zoom=1.8) + view_elevation, view_azimuth; zoom=0.5, show_title=true) Create a 3D Makie plot of wing geometry including panels and filaments. @@ -627,10 +627,11 @@ Create a 3D Makie plot of wing geometry including panels and filaments. - `view_azimuth`: initial view azimuth angle [°] # Keyword arguments -- `zoom`: zoom factor (default: 1.8) +- `zoom`: zoom factor (default: 0.5) +- `show_title`: draw `title` above the axis (default: true) """ function create_geometry_plot_makie(body_aero::BodyAerodynamics, title, - view_elevation, view_azimuth; zoom=0.5) + view_elevation, view_azimuth; zoom=0.5, show_title=true) panels = body_aero.panels va_vec = getfield(body_aero, :va_vec) @@ -638,6 +639,7 @@ function create_geometry_plot_makie(body_aero::BodyAerodynamics, title, fig = Figure(size=(1400, 1400)) ax = Axis3(fig[1, 1]; title=title, + titlevisible=show_title, xlabel="x", ylabel="y", zlabel="z", aspect=:data, azimuth=deg2rad(view_azimuth), @@ -695,7 +697,8 @@ end plot_geometry(body_aero::BodyAerodynamics, title; data_type=nothing, save_path=nothing, is_save=false, is_show=false, - view_elevation=15, view_azimuth=-120, use_tex=false) + view_elevation=15, view_azimuth=-120, use_tex=false, + show_title=true) Makie implementation of [`plot_geometry`](@ref). @@ -711,6 +714,7 @@ Makie implementation of [`plot_geometry`](@ref). - `view_elevation`: View elevation angle in degrees (default: 15) - `view_azimuth`: View azimuth angle in degrees (default: -120) - `use_tex`: Ignored for Makie (default: false) +- `show_title`: Whether to draw the title; it names the files either way (default: true) """ function VortexStepMethod.plot_geometry(body_aero::BodyAerodynamics, title; data_type=nothing, @@ -719,27 +723,21 @@ function VortexStepMethod.plot_geometry(body_aero::BodyAerodynamics, title; is_show=false, view_elevation=15, view_azimuth=-120, - use_tex=false) + use_tex=false, + show_title=true) if is_save - # Angled view - fig = create_geometry_plot_makie(body_aero, "$(title)_angled_view", 15, -120) - save_plot(fig, save_path, "$(title)_angled_view", data_type=data_type) - - # Top view - fig = create_geometry_plot_makie(body_aero, "$(title)_top_view", 90, 0) - save_plot(fig, save_path, "$(title)_top_view", data_type=data_type) - - # Front view - fig = create_geometry_plot_makie(body_aero, "$(title)_front_view", 0, 0) - save_plot(fig, save_path, "$(title)_front_view", data_type=data_type) - - # Side view - fig = create_geometry_plot_makie(body_aero, "$(title)_side_view", 0, -90) - save_plot(fig, save_path, "$(title)_side_view", data_type=data_type) + views = (angled=(15, -120), top=(90, 0), front=(0, 0), side=(0, -90)) + for (view, (elevation, azimuth)) in pairs(views) + view_title = "$(title)_$(view)_view" + fig = create_geometry_plot_makie(body_aero, view_title, elevation, azimuth; + show_title) + save_plot(fig, save_path, view_title; data_type) + end end - fig = create_geometry_plot_makie(body_aero, title, view_elevation, view_azimuth) + fig = create_geometry_plot_makie(body_aero, title, view_elevation, view_azimuth; + show_title) is_show && show_plot(fig; name=title) @@ -758,7 +756,8 @@ span_axis(position, title, ylabel) = """ plot_distribution(y_coordinates_list, results_list, label_list; title="spanwise_distribution", data_type=nothing, - save_path=nothing, is_save=false, is_show=true, use_tex=false) + save_path=nothing, is_save=false, is_show=true, use_tex=false, + show_title=true) Makie implementation of [`plot_distribution`](@ref). @@ -774,6 +773,7 @@ Makie implementation of [`plot_distribution`](@ref). - `is_save`: Whether to save (default: false) - `is_show`: Whether to display (default: true) - `use_tex`: Ignored for Makie (default: false) +- `show_title`: Whether to draw the title; it names the file either way (default: true) """ function VortexStepMethod.plot_distribution(y_coordinates_list, results_list, label_list; title="spanwise_distribution", @@ -781,7 +781,8 @@ function VortexStepMethod.plot_distribution(y_coordinates_list, results_list, la save_path=nothing, is_save=false, is_show=true, - use_tex=false) + use_tex=false, + show_title=true) length(results_list) == length(label_list) || throw(ArgumentError( "Number of results ($(length(results_list))) must match labels ($(length(label_list)))" @@ -789,7 +790,7 @@ function VortexStepMethod.plot_distribution(y_coordinates_list, results_list, la # Create figure with 3x3 grid fig = Figure(size=(1600, 1000)) - Label(fig[0, :], title, fontsize=20) + show_title && Label(fig[0, :], title, fontsize=20) # Row 1: CL, CD, Gamma ax_cl = span_axis(fig[1, 1], "CL Distribution", "Lift Coefficient CL") @@ -1121,7 +1122,8 @@ end view_elevation=15, view_azimuth=-120, is_show=true, use_tex=false, literature_path_list=String[], - data_type=".png", save_path=nothing, is_save=false) + data_type=".png", save_path=nothing, is_save=false, + show_title=true) Makie implementation of [`plot_combined_analysis`](@ref). @@ -1151,6 +1153,7 @@ Makie implementation of [`plot_combined_analysis`](@ref). - `is_save`: Save plots to files (default: false) - `cl_over_cd`: Plot CL/CD vs angle instead of CL vs CD (default: true) - `angle_of_attack_for_spanwise_distribution`: AoA for spanwise plots (default: 5.0) +- `show_title`: Whether to draw the overall title (default: true) """ function VortexStepMethod.plot_combined_analysis( solver, @@ -1174,6 +1177,7 @@ function VortexStepMethod.plot_combined_analysis( is_save=false, angle_of_attack_for_spanwise_distribution=5.0, cl_over_cd=true, + show_title=true, ) # Normalize inputs to arrays for consistent handling solvers = solver isa Vector ? solver : [solver] @@ -1215,7 +1219,7 @@ function VortexStepMethod.plot_combined_analysis( # Fallback if screen detection fails Figure(size=(1800, 1200)) end - Label(fig[0, 1:2], title, fontsize=20, font=:bold) + show_title && Label(fig[0, 1:2], title, fontsize=20, font=:bold) # Use first body_aero for geometry and polar data display first_body = body_aeros[1] @@ -1486,7 +1490,7 @@ Implementation of [`plot_section_polars`](@ref); rendered through `MakieControlP function VortexStepMethod.plot_section_polars(body_aero::BodyAerodynamics; panels=eachindex(body_aero.panels), alphas=deg2rad.(-20:0.5:30), delta=nothing, is_show::Bool=true, is_save::Bool=false, save_path=nothing, - data_type::String=".png") + data_type::String=".png", show_title::Bool=true) panel_indices = vcat(panels) chosen_panels = body_aero.panels[panel_indices] @@ -1496,7 +1500,8 @@ function VortexStepMethod.plot_section_polars(body_aero::BodyAerodynamics; for (i, panel) in zip(panel_indices, chosen_panels)] plt = MakieControlPlots.plotx(rad2deg.(alphas), cl, cd, cm; - xlabel="α [deg]", ylabels=["cl", "cd", "cm"], title="Section polars", + xlabel="α [deg]", ylabels=["cl", "cd", "cm"], + title=show_title ? "Section polars" : "", labels=[labels], disp=(is_show || is_save)) if is_save && !isnothing(save_path) @@ -1734,7 +1739,8 @@ function ObjAdapter.plot_slices_3d(path::String; n_slices::Int=10, rotation=I, end """ - plot_airfoil_fit(x::Vector, y::Vector; title="Airfoil Fit", is_show=true) + plot_airfoil_fit(x::Vector, y::Vector; title="Airfoil Fit", is_show=true, + show_title=true) Plot a single airfoil with its Kulfan CST fit. @@ -1744,15 +1750,17 @@ Plot a single airfoil with its Kulfan CST fit. # Keyword Arguments - `title`: Plot title - `is_show`: Display figure +- `show_title`: Draw the title; it names the window either way # Returns - Makie Figure object and the fitted `KulfanParameters` """ function ObjAdapter.plot_airfoil_fit(x::Vector, y::Vector; title::String="Airfoil Fit", - is_show::Bool=true) + is_show::Bool=true, show_title::Bool=true) fig = Figure(size=(800, 400)) ax = Axis(fig[1, 1]; title=title, + titlevisible=show_title, xlabel="x/c", ylabel="y/c", aspect=DataAspect()) @@ -1790,7 +1798,7 @@ end """ plot_airfoils(geometry_file; overlay=nothing, symmetric=false, idxs=nothing, n_cols=3, is_show=true, is_save=false, - save_path=nothing, data_type=".png") + save_path=nothing, data_type=".png", show_title=true) Makie implementation of [`plot_airfoils`](@ref). @@ -1801,11 +1809,12 @@ becomes unreadable. Both modes show the raw `_raw.dat` slice points as dots with the fitted airfoil as a line. Pass `idxs` (e.g. `idxs=[1]`) to plot only those airfoils by position; otherwise `symmetric=true` shows just the first half of the sections (the wing is mirror-symmetric, so the other half is redundant). +`show_title=false` leaves the `"Airfoils: "` title off the figure. """ function ObjAdapter.plot_airfoils(geometry_file::String; overlay=nothing, symmetric::Bool=false, idxs=nothing, n_cols::Int=3, is_show::Bool=true, is_save::Bool=false, save_path=nothing, - data_type::String=".png") + data_type::String=".png", show_title::Bool=true) airfoils = ObjAdapter.airfoils_from_yaml(geometry_file) isempty(airfoils) && error("No airfoils with a dat_file found in $geometry_file") @@ -1823,7 +1832,8 @@ function ObjAdapter.plot_airfoils(geometry_file::String; ids = [af.id for af in airfoils] crange = (minimum(ids), maximum(ids)) fig = Figure(size=(900, 600)) - ax = Axis(fig[1, 1]; title, xlabel="x/c", ylabel="y/c", aspect=DataAspect()) + ax = Axis(fig[1, 1]; title, titlevisible=show_title, xlabel="x/c", ylabel="y/c", + aspect=DataAspect()) for af in airfoils isempty(af.x_raw) || scatter!(ax, af.x_raw, af.y_raw; color=af.id, colorrange=crange, colormap=:viridis, markersize=3) @@ -1834,7 +1844,7 @@ function ObjAdapter.plot_airfoils(geometry_file::String; ncol = min(n_cols, n) nrow = ceil(Int, n / ncol) fig = Figure(size=(380 * ncol, 320 * nrow)) - Label(fig[0, :], title, fontsize=16) + show_title && Label(fig[0, :], title, fontsize=16) for (i, af) in enumerate(airfoils) ax = Axis(fig[div(i - 1, ncol) + 1, mod1(i, ncol)]; title="Airfoil $(af.id)", xlabel="x/c", ylabel="y/c", diff --git a/src/VortexStepMethod.jl b/src/VortexStepMethod.jl index 6f473f1c..2cf1cd7c 100644 --- a/src/VortexStepMethod.jl +++ b/src/VortexStepMethod.jl @@ -77,6 +77,7 @@ Plot wing geometry from different viewpoints and optionally save/show plots. - `view_elevation`: initial view elevation angle in degrees (default: `15`) - `view_azimuth`: initial view azimuth angle in degrees (default: `-120`) - `use_tex`: use external `pdflatex` for rendering (default: `false`; ignored by Makie) +- `show_title`: draw the title; it names the saved files either way (default: `true`) """ function plot_geometry end @@ -97,6 +98,7 @@ Plot spanwise distributions of aerodynamic properties. - `is_save`: whether to save (default: `false`) - `is_show`: whether to display (default: `true`) - `use_tex`: use external `pdflatex` for rendering (default: `false`; ignored by Makie) +- `show_title`: draw the title; it names the saved file either way (default: `true`) """ function plot_distribution end @@ -172,6 +174,7 @@ in sequence. - `save_path`: directory to save files (default: `nothing`) - `is_save`: whether to save (default: `false`) - `cl_over_cd`: plot CL/CD vs angle (default: `true`) +- `show_title`: draw the overall title (default: `true`) """ function plot_combined_analysis end @@ -196,6 +199,7 @@ Rendered through `MakieControlPlots`; returns its plot object. - `is_save`: whether to save (default: `false`) - `save_path`: directory to save the figure (default: `nothing`) - `data_type`: file extension for saving (default: `".png"`) +- `show_title`: draw the title (default: `true`) """ function plot_section_polars end From aa41be8790f8f8acb281d61d0e79e9a5b62e2a62 Mon Sep 17 00:00:00 2001 From: 1-Bort-1 <323661610+1-Bort-1@users.noreply.github.com> Date: Wed, 23 Sep 2026 12:42:51 +0200 Subject: [PATCH 3/3] Name the geometry view loop variable view_name, skip saving where the test only reads titles Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 2 +- ext/VortexStepMethodMakieExt.jl | 4 ++-- test/plotting/test_plotting.jl | 3 +-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f905a24..1433def7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,7 @@ - `plot_geometry`, `plot_distribution`, `plot_combined_analysis`, `plot_section_polars`, `plot_airfoil_fit` and `plot_airfoils` take `show_title=true`; with `false` the title - is not drawn, and it still names the saved file and the window where it did. + is not drawn, and still names the saved file and window. ## VortexStepMethod v6.0.0 2026-09-23 diff --git a/ext/VortexStepMethodMakieExt.jl b/ext/VortexStepMethodMakieExt.jl index 551932ba..ad8d74b2 100644 --- a/ext/VortexStepMethodMakieExt.jl +++ b/ext/VortexStepMethodMakieExt.jl @@ -728,8 +728,8 @@ function VortexStepMethod.plot_geometry(body_aero::BodyAerodynamics, title; if is_save views = (angled=(15, -120), top=(90, 0), front=(0, 0), side=(0, -90)) - for (view, (elevation, azimuth)) in pairs(views) - view_title = "$(title)_$(view)_view" + for (view_name, (elevation, azimuth)) in pairs(views) + view_title = "$(title)_$(view_name)_view" fig = create_geometry_plot_makie(body_aero, view_title, elevation, azimuth; show_title) save_plot(fig, save_path, view_title; data_type) diff --git a/test/plotting/test_plotting.jl b/test/plotting/test_plotting.jl index 974ee8ed..575937a1 100644 --- a/test/plotting/test_plotting.jl +++ b/test/plotting/test_plotting.jl @@ -184,8 +184,7 @@ end @test fig isa Figure @testset "show_title=false hides the title but still names the file" begin - fig = plot_geometry(body_aero, "Hidden geometry"; save_path=save_dir, - is_save=true, is_show=false) + fig = plot_geometry(body_aero, "Hidden geometry"; is_show=false) @test "Hidden geometry" in drawn_titles(fig) fig = plot_geometry(body_aero, "Hidden geometry"; data_type=".png", save_path=save_dir, is_save=true, is_show=false, show_title=false)