Automatically insert variable name or symbol in Title and Colorbar

I have many different variable names or symbols for different data.
I will insert one of those variable at a time in my safe_log( ) function. I expect cbar.label and ax.title to accept that variable name automatically rather than changing variable name manually at every place.
For example i want to insert Ψ variable name or symbol in my plot’s Title and color bar.

using GLMakie
z_log = safe_log.(Ψ)
ax.title = "Ψ variable Plot"
cbar.label = L"log(Ψ)"

Functions cannot know about the names of the variables passed to them. You either need to write a macro that then passes both name and variable to the function as two separate arguments, or use a dictionary to hold your variables, then you can pass a string or symbol directly and retrieve the data this way.

1 Like

Please can you explain how to use macro? If i use $ then the values contained in variable name or symbol get printed on plot.

function m(s::Symbol, value)
    println("The symbol is $s and the value is $value")
end

macro m(variable::Symbol)
    :(m($(QuoteNode(variable)), $(esc(variable))))
end
julia> x = 1
1

julia> @m(x)
The symbol is x and the value is 1
3 Likes

Sorry, You misunderstood. I have a variable Ψ and i will insert its data in safe_log( ) function. After that i will insert that variable Ψ in cbar.label and ax.title to plot symbol Ψ in title and color bar.

safe_log(x::Float64) = x > 0 ? log(x) : 1.0
# Insert variable that you want to plot in z_log function.
z_log = safe_log.(Ψ)

You should provide a proper MWE - in your first post you aren’t actually creating a plot at all.

Both your initial post and your reply above seem to suggest that what you’re trying to do is exactly what @jules describes, so if you’re actually trying to do something else you need to be more explicit about what that is.

1 Like

Please can you give dictionary way example. Thanks.
I got error while using @m( ) inside another function.

ERROR: LoadError: UndefVarError: value not defined in Main
Suggestion: check for spelling errors or missing imports.
Stacktrace:
[1] main(directory::String, N_r::Int64, N_θ::Int64, r::Vector{Float64}, θ::Vector{Float64}, μ::Float64, dms::Int64)
@ Main ~/Videos/cos_veloclect.jl:95
[2] macro expansion

If i define m function and macro inside my function then i get local error.

julia> using GLMakie

julia> data = Dict("ψ" => rand(10))
Dict{String, Vector{Float64}} with 1 entry:
  "ψ" => [0.687504, 0.0257956, 0.282592, 0.390958, 0.285716, 0.466667, 0.817611, 0.601683, 0.142801, 0.138936]

julia> function plot_a_variable(varlabel, data_dict)
           lines(data_dict[varlabel], axis = (; title = "A plot of $varlabel"))
       end
plot_a_variable (generic function with 1 method)

julia> plot_a_variable("ψ", data)

Please see this MWE. My data is available at :point_down: that earlier post. What modifications should i do in my code so that i have to change variable(here Ψ) only at single place.

using GLMakie, Meshes

x = include("x.jl")  # Matrix of x-coordinates
z = include("z.jl")  # Matrix of z-coordinates
Ψ = include("psi.jl")  # Data matrix
grd = StructuredGrid(x, z)

function m(s::Symbol, value)
    println("The symbol is $s ")
end
macro m(variable::Symbol)
    :(m($(QuoteNode(variable)), $(esc(variable))))
end
@m(Ψ)

safe_log(x::Float64) = x > 0 ? log(x) : 1.0
z_log = safe_log.(Ψ)
fig, ax, plt = Meshes.viz(grd, color=vec(z_log), colorscheme=:jet)
ax.title = "Ψ and Contour Plot (data.$file)"
cbar = Colorbar(fig[1, 2])
cbar.label = L"log(Ψ)"
# Save the plot
save("Demo_Meshes.png", fig)
display(fig)

I get this error on using $value.

julia> z_log = safe_log.($value)

ERROR: syntax: “$” expression outside quote around REPL[10]:1
Stacktrace:
[1] top-level scope
@ REPL[10]:1

You were meant to transfer the macro technique I showed you to your own function :slight_smile: if you just call @m nothing happens to your own code, it was an example

1 Like

I have defined my function for Ψ as :point_down:

function alfven_surface!(v_x, v_z, B_x, B_z, sinθ, cosθ, vp2, bp2, alfsurf, ρ, tracer)::Array{Float64, 2}
	@. vp2 = v_x^2 + v_z^2
	@. bp2 = B_x^2 + B_z^2
	@. alfsurf = 4.0 * π * ρ * vp2 / bp2
    @inbounds @. alfsurf[(alfsurf .> 1.0) & (tracer .> 0.1)] = 0.0
    return Ψ
end
Ψ = alfven_surface!(v_x, v_z, B_x, B_z, sinθ, cosθ, vp2, bp2, alfsurf, ρ, tracer)

so what changes should i do?

It doesn’t matter how the variable is computed, your plotting code is the one that needs changing

1 Like

@jules Should i do changes in above or below function? Please explain in detail.

Funnel the variable name into your plotting code so that you can use it in the labels. Do that by wrapping everything in a macro like I showed above

Never had a reason to use macros before but I really liked @jules simple example above and wanted to try.

Maybe this would work for you @raman_kumar if you wrap your plotting code similarly?

using GLMakie

ψ = rand(100)
χ = rand(100)

function m(s::Symbol, values)
	exp_val = exp.(values)
	fig, ax, plt = scatter(exp_val)
	ax.title = "Plot of $s"
	return fig, ax, plt
end

macro m(variable::Symbol)
	:(m($(QuoteNode(variable)), $(esc(variable))))
end

fig1, ax1, plt1 = @m ψ
fig2, ax2, plt2 = @m χ
2 Likes
See this code
using GLMakie, Meshes

x = include("x.jl")  # Matrix of x-coordinates
z = include("z.jl")  # Matrix of z-coordinates
Ψ = include("alfsurf.jl")  # Data matrix
grd = StructuredGrid(x, z)

@m(Ψ)
safe_log(x::Float64) = x > 0 ? log(x) : 1.0
function m(s::Symbol, value)
	z_log = safe_log.($value)
	fig, ax, plt = Meshes.viz(grd, color=vec(z_log), colorscheme=:jet)
	ax.title = " $s and Contour Plot"
	cbar = Colorbar(fig[1, 2])
	cbar.label = L"log($s)"
	return fig, ax, plt
end

macro m(variable::Symbol)
    :(m($(QuoteNode(variable)), $(esc(variable))))
end
fig1, ax1, plt = @m ψ

# Save the plot
save("Demo_Meshes.png", fig)
display(fig)

gives error after below function code.

function m(s::Symbol, value)
	z_log = safe_log.($value)
	fig, ax, plt = Meshes.viz(grd, color=vec(z_log), colorscheme=:jet)
	ax.title = " $s and Contour Plot"
	cbar = Colorbar(fig[1, 2])
	cbar.label = L"log($s)"
	return fig, ax, plt
end

ERROR: syntax: “$” expression outside quote around REPL[67]:2
Stacktrace:
[1] top-level scope
@ REPL[67]:1

This line

z_log = safe_log.($value)

should not have the $ since value is already an array with the values that you want to call safe_log() on.

So I think you should replace that line with:

z_log = safe_log.(value)

Also, in the code you provided above, save() and display() will error because fig is undefined. That should be fig1.

1 Like

Thank you very much everyone. For me this code worked fine.

using GLMakie, Meshes

x = include("x.jl")  # Matrix of x-coordinates
z = include("z.jl")  # Matrix of z-coordinates
Ψ = include("alfsurf.jl")  # Data matrix
grd = StructuredGrid(x, z)

safe_log(x::Float64) = x > 0 ? log(x) : 1.0
function m(s::Symbol, value)
	z_log = safe_log.(value)
	fig, ax, plt = Meshes.viz(grd, color=vec(z_log), colorscheme=:jet)
	ax.title = " $s and Contour Plot"
	cbar = Colorbar(fig[1, 2])
	cbar.label = "log($s)"
	return fig, ax, plt
end

macro m(variable::Symbol)
    :(m($(QuoteNode(variable)), $(esc(variable))))
end
fig, ax, plt = @m Ψ

# Save the plot
save("Demo_Meshes.png", fig)
display(fig)

1 Like