Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/GMT.jl
Original file line number Diff line number Diff line change
Expand Up @@ -398,7 +398,7 @@ using .Laszip
grdimage(I, V=:q)
grdview(rand(Float32, 32, 32), Vd=2)
grdinfo(mat2grid(rand(Float32, 4, 4)))
Glix = gmt("grdmath", "-R0/10/0/10 -I2 X")
Glix = gmt("grdmath -R0/10/0/10 -I2 X")
gmt_grdinfo_C(Glix)
grdcontour(Glix)
grd2cpt(Glix)
Expand Down
81 changes: 41 additions & 40 deletions src/common_options.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2406,8 +2406,8 @@ function add_opt(d::Dict, cmd::String, opt::String, symbs::VMs, mapa; grow_mat=n
end

# ---------------------------------------------------------------------------------------------------
function genFun(this_key::Symbol, user_input::NamedTuple, mapa::NamedTuple)::String
(!haskey(mapa, this_key)) && return # Should it be a error?
function genFun(this_key::Symbol, user_input::NamedTuple, mapa)::String
(!haskey(mapa, this_key)) && return "" # Should it be a error?
out::String = ""
key = keys(user_input) # user_input = (rows=1, fill=:red)
val_namedTup = mapa[this_key] # water=(rows="my", cols="mx", fill=add_opt_fill)
Expand All @@ -2425,76 +2425,82 @@ function genFun(this_key::Symbol, user_input::NamedTuple, mapa::NamedTuple)::Str
end

# ---------------------------------------------------------------------------------------------------
function add_opt(nt::NamedTuple, mapa::NamedTuple, arg=nothing)::String
function add_opt(nt::NamedTuple, mapa::NamedTuple, arg=Float64[])::String # This wrapper is the only who gets recompiled when arg changes
_arg = (arg === nothing || isempty(arg)) ? Float64[] : arg
add_opt_1(nt, nt2dict(mapa), _arg)
end
function add_opt_1(nt::NamedTuple, d, arg)::String #
#function add_opt(nt::NamedTuple, mapa::NamedTuple, arg=nothing)::String
# Generic parser of options passed in a NT and whose last element is another NT with the mapping
# between expanded sub-options names and the original GMT flags.
# ARG, is a special case to append to a matrix (can't realy be done in Julia)
# Example:
# add_opt((a=(1,0.5),b=2), (a="+a",b="-b"))
# translates to: "+a1/0.5-b2"
key = keys(nt); # The keys actually used in this call
d = nt2dict(mapa) # The flags mapping as a Dict (all possible flags of the specific option)
#d = nt2dict(mapa) # The flags mapping as a Dict (all possible flags of the specific option)
cmd::String = ""; cmd_hold = Vector{String}(undef, 2); order = zeros(Int,2,1); ind_o = 0
count = zeros(Int, length(key))
for k = 1:numel(key)::Int # Loop over the keys of option's tuple
!haskey(d, key[k]) && continue
count[k] = k
isa(nt[k], Dict) && (nt[k] = Base.invokelatest(dict2nt, nt[k]))
if (isa(d[key[k]], Tuple)) # Complexify it. Here, d[key[k]][2] must be a function name.
this_val = d[key[k]]
if (isa(this_val, Tuple)) # Complexify it. Here, d[key[k]][2] must be a function name.
if (isa(nt[k], NamedTuple))
if (d[key[k]][2] == add_opt_fill)
cmd *= string(d[key[k]][1])::String * d[key[k]][2]("", Dict(key[k] => nt[k]), [key[k]])::String
if (this_val[2] == add_opt_fill)
cmd *= string(this_val[1])::String * this_val[2]("", Dict(key[k] => nt[k]), [key[k]])::String
else
local_opt = (d[key[k]][2] == helper_decorated) ? true : nothing # 'true' means single argout
cmd *= string(d[key[k]][1])::String * d[key[k]][2](nt2dict(nt[k]), local_opt)::String
local_opt = (this_val[2] == helper_decorated) ? true : nothing # 'true' means single argout
cmd *= string(this_val[1])::String * this_val[2](nt2dict(nt[k]), local_opt)::String
end
else #
if (length(d[key[k]]) == 2) # Run the function
cmd *= string(d[key[k]][1])::String * d[key[k]][2](Dict(key[k] => nt[k]), [key[k]])::String
if (length(this_val) == 2) # Run the function
cmd *= string(this_val[1])::String * this_val[2](Dict(key[k] => nt[k]), [key[k]])::String
else # This branch is to deal with options -Td, -Tm, -L and -D of basemap & psscale
ind_o += 1
(ind_o > 2) && (@warn("You passed more than 1 of the exclusive options in a anchor type option, keeping first but this may break."); ind_o = 1)
if (d[key[k]][2] === nothing) cmd_hold[ind_o] = d[key[k]][1] # Only flag char and order matters
elseif (length(d[key[k]][1]) == 2 && d[key[k]][1][1] == '-' && !isa(nt[k], Tuple)) # e.g. -L (&g, arg2str, 1)
cmd_hold[ind_o] = string(d[key[k]][1][2]) # where g<scalar>
if (this_val[2] === nothing) cmd_hold[ind_o] = this_val[1] # Only flag char and order matters
elseif (length(this_val[1]) == 2 && this_val[1][1] == '-' && !isa(nt[k], Tuple)) # e.g. -L (&g, arg2str, 1)
cmd_hold[ind_o] = string(this_val[1][2]) # where g<scalar>
else # Run the fun
cmd_hold[ind_o] = (d[key[k]][1] == "") ? d[key[k]][2](nt[k]) : string(d[key[k]][1][end])::String * d[key[k]][2](nt[k])::String
cmd_hold[ind_o] = (this_val[1] == "") ? this_val[2](nt[k]) : string(this_val[1][end])::String * this_val[2](nt[k])::String
end
order[ind_o] = d[key[k]][3]; # Store the order of this sub-option
order[ind_o] = this_val[3]; # Store the order of this sub-option
end
end
elseif (isa(d[key[k]], NamedTuple)) #
elseif (isa(this_val, NamedTuple)) #
if (isa(nt[k], NamedTuple))
cmd *= genFun(key[k], nt[k], mapa)::String
cmd *= genFun(key[k], nt[k], d)::String
else # Create a NT where value = key. For example for: surf=(waterfall=:rows,)
if (!isa(nt[1], Tuple)) # nt[1] may be a symbol, or string. E.g. surf=(water=:cols,)
cmd *= genFun(key[k], (; Symbol(nt[1]) => nt[1]), mapa)::String
cmd *= genFun(key[k], (; Symbol(nt[1]) => nt[1]), d)::String
else
if ((val = find_in_dict(d, [key[1]])[1]) !== nothing) # surf=(waterfall=(:cols,:red),)
cmd *= genFun(key[k], (; Symbol(nt[1][1]) => nt[1][1], keys(val)[end] => nt[1][end]), mapa)::String
cmd *= genFun(key[k], (; Symbol(nt[1][1]) => nt[1][1], keys(val)[end] => nt[1][end]), d)::String
end
end
end
elseif (d[key[k]] == "1") # Means that only first char in value is retained. Used with units
elseif (this_val == "1") # Means that only first char in value is retained. Used with units
t::String = arg2str(nt[k])::String
if (t != "") cmd *= t[1]
else cmd *= "1" # "1" is itself the flag
end
elseif (d[key[k]] != "" && d[key[k]][1] == '|') # Potentialy append to the arg matrix (here in vector form)
elseif (this_val != "" && this_val[1] == '|') # Potentialy append to the arg matrix (here in vector form)
if (isa(nt[k], AbstractArray) || isa(nt[k], Tuple))
if (isa(nt[k], AbstractArray)) append!(arg, reshape(nt[k], :))
else append!(arg, reshape(collect(nt[k]), :))
end
end
cmd *= string(d[key[k]][2:end])::String # And now append the flag
elseif (d[key[k]] != "" && d[key[k]][1] == '_') # Means ignore the content, only keep the flag
cmd *= string(d[key[k]][2:end])::String # Just append the flag
elseif (d[key[k]] != "" && d[key[k]][end] == '1') # Means keep the flag and only first char of arg
cmd *= string(d[key[k]][1:end-1])::String * string(string(nt[k])[1])::String
elseif (d[key[k]] != "" && d[key[k]][end] == '#') # Means put flag at the end and make this arg first in cmd (coast -W)
cmd = arg2str(nt[k])::String * string(d[key[k]][1:end-1])::String * cmd
cmd *= string(this_val[2:end])::String # And now append the flag
elseif (this_val != "" && this_val[1] == '_') # Means ignore the content, only keep the flag
cmd *= string(this_val[2:end])::String # Just append the flag
elseif (this_val != "" && this_val[end] == '1') # Means keep the flag and only first char of arg
cmd *= string(this_val[1:end-1])::String * string(string(nt[k])[1])::String
elseif (this_val != "" && this_val[end] == '#') # Means put flag at the end and make this arg first in cmd (coast -W)
cmd = arg2str(nt[k])::String * string(this_val[1:end-1])::String * cmd
else
cmd *= d[key[k]]::String * arg2str(nt[k])::String
cmd *= this_val::String * arg2str(nt[k])::String
end
end

Expand All @@ -2509,14 +2515,6 @@ function add_opt(nt::NamedTuple, mapa::NamedTuple, arg=nothing)::String
end
if (occursin(':', cmd_hold[last])) # It must be a geog coordinate in dd:mm
cmd = "g" * cmd
#=
elseif (length(cmd_hold[last]) > 2) # Temp patch to avoid parsing single char flags
rs = split(cmd_hold[last], '/')
if (length(rs) == 2)
x = tryparse(Float64, rs[1]); y = tryparse(Float64, rs[2]);
if (x !== nothing && y !== nothing && 0 <= x <= 1.0 && 0 <= y <= 1.0 && !occursin(r"[gjJxn]", string(cmd[1]))) cmd = "n" * cmd end # Otherwise, either a paper coord or error
end
=#
end
end

Expand Down Expand Up @@ -2824,7 +2822,7 @@ function makecpt_raw(cmd::String, arg1=nothing)::GMTcpt
# Raw version that already knows what the command is and has no input data.
(IamModern[] && !contains(cmd, " -H")) && (cmd *= " -H")
!startswith(cmd, "makecpt ") && (cmd = "makecpt " * cmd)
_r = gmt_GMTcpt(cmd, arg1)
_r = arg1 === nothing ? gmt_GMTcpt(cmd) : gmt_GMTcpt(cmd, arg1)
r::GMTcpt = (_r !== nothing) ? _r : GMTcpt() # _r === nothing when we save CPT on disk.
(contains(cmd, " -N") && !isempty(r)) && (r.bfn = ones(3,3)) # Cannot remove the bfn like in plain GMT so make it all whites
CURRENT_CPT[] = r
Expand Down Expand Up @@ -4110,8 +4108,11 @@ function common_grd(d::Dict, cmd::String, args...)
(haskey(d, :Vd) && d[:Vd] > 2) && show_args_types(args...)
show_non_consumed(d, cmd)
(dbg_print_cmd(d, cmd) !== nothing) && return cmd # Vd=2 cause this return

# First case below is of a ARGS tuple(tuple) with all numeric inputs.
R = isa(args, Tuple{Tuple}) ? gmt(cmd, args[1]...) : gmt(cmd, args...)
n_args = 0
for k = 1:numel(args) if (args[k] !== nothing) n_args += 1 end end # Drop the nothings
R = isa(args, Tuple{Tuple}) ? gmt(cmd, args[1]...) : gmt(cmd, args[1:n_args]...)
(isGMTdataset(R) && contains(cmd, " -fg") && getproj(R) == "") && (isa(R, GMTdataset) ? R.proj4 = prj4WGS84 : R[1].proj4 = prj4WGS84)
return R
end
Expand Down
23 changes: 23 additions & 0 deletions src/gmt_main.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,27 @@ except when using the ``monolithic`` mode. Usage:
gmt("module_name `options`", args...)
"""
function gmt(cmd::String, args...)
n_argin::Int = length(args)
if (n_argin > 0)
if (isa(args[1], String))
tok::String, r::String = strtok(cmd)
if (r == "") # User gave 'module' separately from 'options'
error("Please use gmt(\"module_name options\", args...) instead of gmt(\"module_name\", \"options\", args...)")
#cmd::String *= " " * args[1]::String # Cat with the progname and so pretend input followed the classic construct
#args = args[2:end]
#n_argin -= 1
end
end
# We may have trailing [] args in modules
baka = n_argin
while (n_argin > 0 && (args[n_argin] === nothing)) n_argin -= 1 end
#baka != n_argin && println("-----------------------------------------> $cmd has $(baka-n_argin) empty args.")
baka != n_argin && (args = args[1:n_argin])
end
_gmt(cmd, args...)
end

function _gmt(cmd::String, args...)

(cmd == "") && return nothing # Building docs with Quarto leads here when examples use ModernMode
(cmd == "destroy") && return gmt_restart()
Expand All @@ -13,6 +34,7 @@ function gmt(cmd::String, args...)

# ----------- Minimal error checking ------------------------
n_argin::Int = length(args)
#=
if (n_argin > 0)
if (isa(args[1], String))
tok::String, r::String = strtok(cmd)
Expand All @@ -25,6 +47,7 @@ function gmt(cmd::String, args...)
# We may have trailing [] args in modules
while (n_argin > 0 && (args[n_argin] === nothing)) n_argin -= 1 end
end
=#
# -----------------------------------------------------------

# 1. Get arguments, if any, and extract the GMT module name
Expand Down
8 changes: 5 additions & 3 deletions src/psconvert.jl
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""
psconvert(cmd0::String="", arg1=nothing; kwargs...)

Place images or EPS files on maps.
Convert [E]PS file(s) to other formats using Ghostscript.

Parameters
----------
Expand Down Expand Up @@ -77,9 +77,10 @@ end

function psconvert_helper(cmd0::String, arg1, d::Dict{Symbol,Any})

if (!isempty(cmd0)) && (arg1 === nothing) arg1 = cmd0 end
if (!isempty(cmd0)) && (arg1 === nothing) arg1 = cmd0 end # This is stupid, must be fixed.

cmd::String = add_opt(d, "", "A", [:A :adjust :crop])
cmd::String = add_opt(d, "", "A", [:A :adjust :crop :bbox], (round="_+r", nostamp="_+u", bbox="_+i"))
needs_Te = contains(cmd, "+i")
(cmd == " -A") && (cmd = cmd * "1p") # If just -A default to -A1p
cmd = parse_these_opts(cmd, d, [[:D :out_dir :output_dir], [:E :dpi], [:F :out_name :output_name],
[:G :ghost_path], [:I :resize], [:L :list_file], [:M :embed], [:N :bgcolor], [:P :portrait], [:Q :anti_aliasing], [:S :gs_command], [:Z :del_input_ps]])
Expand All @@ -96,6 +97,7 @@ function psconvert_helper(cmd0::String, arg1, d::Dict{Symbol,Any})
else
cmd = add_opt(d, cmd, "T", [:T :format])
end
(needs_Te && !contains(cmd, " -Te")) && (cmd *= " -Te") # We need this when -A+i (bbox) to precent gmt() to try return an image

if ((val = find_in_dict(d, [:C :gs_option])[1]) !== nothing)
if (isa(val, String) || isa(val, Symbol))
Expand Down
2 changes: 1 addition & 1 deletion test/test_B-GMTs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@
gmtsimplify([0.0 0; 1.1 1.1; 2 2.2; 3.3 3], T="3k")

println(" GMTREADWRITE")
G=gmt("grdmath", "-R0/10/0/10 -I1 5");
G=gmt("grdmath -R0/10/0/10 -I1 5");
gmtwrite("lixo.grd", G, scale=10, offset=-10)
GG = gmtread("lixo.grd", grd=true, varname=:z);
GG = gmtread("lixo.grd", varname=:z);
Expand Down
12 changes: 6 additions & 6 deletions test/test_GRDs.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
println(" GRDINFO")
G=gmt("grdmath", "-R0/10/0/10 -I1 5");
G=gmt("grdmath -R0/10/0/10 -I1 5");
r=gmt("grdinfo -C", G);
@assert(r.data[1:1,1:10] == [0.0 10.0 0.0 10.0 5.0 5.0 1.0 1.0 11.0 11.0])
r2=grdinfo(G, C=true, V=:q);
Expand All @@ -12,7 +12,7 @@
grdinfo(G);

println(" GRD2CPT")
G=gmt("grdmath", "-R0/10/0/10 -I2 X");
G=gmt("grdmath -R0/10/0/10 -I2 X");
C=grd2cpt(G);
grd2cpt(G, cmap="lixo.cpt", V="q")

Expand All @@ -24,11 +24,11 @@
@assert(sum(D1.data) == sum(D2.data))

println(" GRD2KML")
G=gmt("grdmath", "-R0/10/0/10 -I1 X -fg");
G=gmt("grdmath -R0/10/0/10 -I1 X -fg");
grd2kml(G, I="+", N="NUL", V="q", Vd=dbg2)

println(" GRDBLEND")
G3=gmt("grdmath", "-R5/15/0/10 -I1 X Y -Vq");
G3=gmt("grdmath -R5/15/0/10 -I1 X Y -Vq");
grdblend(G,G3);

println(" GRDCLIP")
Expand Down Expand Up @@ -56,7 +56,7 @@
grdcontour!(G, axis="a", color=cpt, pen="+c", X=1, Y=1, N=cpt, Vd=dbg2)

println(" GRDCUT")
G=gmt("grdmath", "-R0/10/0/10 -I1 X Y MUL");
G=gmt("grdmath -R0/10/0/10 -I1 X Y MUL");
grdcut(G, limits=[3 9 2 8]);
grdcut("lixo.grd", limits=[3 9 2 8], V=:q); # lixo.grd was written above in the gmtwrite test
grdcut(data="lixo.grd", limits=[3 9 2 8], V=:q);
Expand Down Expand Up @@ -163,7 +163,7 @@
grdsample(G, inc=0.5); # Use G of previous test

println(" GRDTREND")
G = gmt("grdmath", "-R0/10/0/10 -I1 X Y MUL");
G = gmt("grdmath -R0/10/0/10 -I1 X Y MUL");
grdtrend(G, model=3);
mat2grid(ones(Float32, size(G.z,1), size(G.z,2)));
W = mat2grid(rand(16,16), x=11:26, y=1:16);
Expand Down
2 changes: 1 addition & 1 deletion test/test_misc.jl
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@
@test D + D == [2 2; 2 2; 2 2]
@test D - D == [0 0; 0 0; 0 0]

D2=grd2xyz(gmt("grdmath", "-R0/10/0/10 -I2 X"))
D2=grd2xyz(gmt("grdmath -R0/10/0/10 -I2 X"))
cat(D, D2);
cat([D], D2);
cat([D], [D2]);
Expand Down
2 changes: 1 addition & 1 deletion test/test_views.jl
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ grdview!(G, G=G, J="X6i", JZ=5, I=45, Q="s", C="topo", R="-15/15/-15/15/-1/1",
r = grdview!(G, plane=(-6,:lightgray), surftype=(surf=true,mesh=:red), view="120/30", Vd=dbg2);
@test startswith(r, "grdview -R-15.0/15.0/-15.0/15.0/-1.0/1.0 -J -n+a -p120/30 -N-6+glightgray -Qsmred")
r = grdview(G, surf=(waterfall=(:rows,:red),surf=true, mesh=true, img=50), Vd=dbg2);
@test startswith(r, "grdview -R0/360/-90/90 -JX" * split(GMT.DEF_FIG_SIZE, '/')[1] * "/0" * " -Baf -Bza -n+a -Qmyredsmi50")
@test startswith(r, "grdview -R0/360/-90/90 -JX" * split(GMT.DEF_FIG_SIZE, '/')[1] * "/0" * " -Baf -Bza -n+a -Qsmi50")
@test startswith(grdview(G, surf=(waterfall=:rows,), Vd=dbg2), "grdview -R0/360/-90/90 -JX" * split(GMT.DEF_FIG_SIZE, '/')[1] * "/0" * " -Baf -Bza -n+a -Qmy")
@test startswith(grdview(G, surf=(waterfall=(rows=true, fill=:red),), Vd=dbg2), "grdview -R0/360/-90/90 -JX" * split(GMT.DEF_FIG_SIZE, '/')[1] * "/0" * " -Baf -Bza -n+a -Qmyred")
@test_throws ErrorException("Wrong way of setting the drape (G) option.") grdview(rand(16,16), G=(1,2))
Expand Down
Loading