From afbd0f1bf98d2d9d6fbfa6b3794fede0cb251738 Mon Sep 17 00:00:00 2001 From: Joaquim Date: Tue, 29 Aug 2023 20:12:23 +0100 Subject: [PATCH 1/4] Comment an apparently not used function. --- src/show_pretty_datasets.jl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/show_pretty_datasets.jl b/src/show_pretty_datasets.jl index 1b6d7c46a..041198029 100644 --- a/src/show_pretty_datasets.jl +++ b/src/show_pretty_datasets.jl @@ -208,6 +208,7 @@ function batch_compacttype(types::Vector{Any}, maxwidths::Vector{Int}) end end +#= function batch_compacttype(types::Vector{Any}, maxwidth::Int) cache = Dict{Type, String}() return map(types) do T @@ -216,6 +217,7 @@ function batch_compacttype(types::Vector{Any}, maxwidth::Int) end end end +=# """ compacttype(T::Type, maxwidth::Int=8, initial::Bool=true) From d8078f6772e28203da279e04497cf9c9f5981145 Mon Sep 17 00:00:00 2001 From: Joaquim Date: Tue, 29 Aug 2023 20:15:26 +0100 Subject: [PATCH 2/4] Rework the getbyattrib function to select more elements. Make filter and findall aliases of it. --- src/utils_types.jl | 69 +++++++++++++++++++++++++++++----------- test/test_common_opts.jl | 5 ++- test/test_misc.jl | 2 +- 3 files changed, 56 insertions(+), 20 deletions(-) diff --git a/src/utils_types.jl b/src/utils_types.jl index 6644236fa..6f1c6a201 100644 --- a/src/utils_types.jl +++ b/src/utils_types.jl @@ -1892,17 +1892,28 @@ end # --------------------------------------------------------------------------------------------------- """ - getbyattrib(D::Vector{<:GMTdataset}[, index::Bool]; kw...) + getbyattrib(D::Vector{<:GMTdataset}[, index::Bool=false]; kw...) -Take a GMTdataset vector and return only its elememts that match the condition(s) set by the `attrib` keywords. +or + + filter(D::Vector{<:GMTdataset}; kw...) +or + + findall(D::Vector{<:GMTdataset}; kw...) + +Take a GMTdataset vector and return only its elements that match the condition(s) set by the `kw` keywords. Note, this assumes that `D` has its `attrib` fields set with usable information. +NOTE: Instead of ``getbyattrib`` one case use instead ``filter`` (==> `index=false`) or ``findall`` (==> `index=true`) + ### Parameters -- `attrib` or `att`: keyword with the attribute `name` used in selection. It can be a single name as in `att="NAME_2"` - or a NamedTuple with the attribname, attribvalue as in `att=(NAME_2="value")`. Use more elements if - wishing to do a composite match. E.g. `att=(NAME_1="val1", NAME_2="val2")` in which case oly segments - matching the two conditions are returned. -- `val` or `value`: keyword with the attribute ``value`` used in selection. Use this only when `att` is not a NamedTuple. +- `attrib name(s)=value(s)`: Easier to explain by examples: `NAME="Antioquia"`, select all elements that have + that attribute/value combination. `NAME=("Antioquia", "Caldas"), pick elements that have those `NAME` attributes. + Add as many as wished. If using two `kwargs` the second works as a condition. ``(..., NAME=("Antioquia", "Caldas"), feature_id=0)`` + means select all elements from ``Antioquia`` and ``Caldas`` that have the attribute `feature_id` = 0. +- `attrib` or `att`: (OLD SYNTAX) A NamedTuple with the attribname, attribvalue as in `att=(NAME_2="value",)`. + Use more elements if wishing to do a composite match. E.g. `att=(NAME_1="val1", NAME_2="val2")` in which + case only segments matching the two conditions are returned. - `index`: Use this `positional` argument = `true` to return only the segment indices that match the `att` condition(s). ### Returns @@ -1911,31 +1922,49 @@ Or `nothing` if the query results in an empty GMTdataset ## Example: - D = getbyattrib(D, attrib="NAME_2", val="Porto"); + D = filter(D, NAME_2="Porto"); """ function getbyattrib(D::Vector{<:GMTdataset}, ind_::Bool; kw...)::Vector{Int} # This method does the work but it's not the one normally used by the public. # It returns the indices of the selected segments. (isempty(D[1].attrib)) && (@warn("This datset does not have an `attrib` field and is hence unusable here."); return Int[]) - ((_att = find_in_kwargs(kw, [:att :attrib])[1]) === nothing) && error("Must provide the `attribute` NAME.") - if isa(_att, NamedTuple) - atts, vals = string.(keys(_att)), string.(values(_att)) + dounion = Int(1e9) # Just a big number + if ((_att = find_in_kwargs(kw, [:att :attrib])[1]) !== nothing) # For backward compat. + atts, vals = isa(_att, NamedTuple) ? (string.(keys(_att)), string.(values(_att))) : ((string(_att),), (string(val),)) else - atts = (string(_att),) - ((val = find_in_kwargs(kw, [:val :value])[1]) === nothing) && error("Must provide the `attribute` VALUE.") - vals = (string(val),) + # FCK unbelievable case. Julia can be f. desparing. It took me an whole afternoon to make this work. + #d = KW(kw); Keys = keys(d); + #Keys[1] => Internal Error: MethodError: no method matching getindex(::Base.KeySet{Symbol, Dict{Symbol, Any}}, ::Int64) + count, kk = 0, 1 + v = values(kw) + for k = 1:numel(kw) count += (isa(values(v[k]), Tuple)) ? length(values(v[k])) : 1 end + atts, vals = Vector{String}(undef, count), Vector{String}(undef, count) + + _keys = string.(keys(kw)) + for k = 1:numel(kw) + vv = values(v[k]) + if (isa(vv, Tuple)) + atts[kk:kk+length(vv)-1] .= _keys[k] + vals[kk:kk+length(vv)-1] .= string.(vv) + kk += length(vv) + else + atts[kk], vals[kk] = _keys[k], string(vv) + kk += 1 + end + (k == 1) && (dounion = kk) # Index that separates the unions from the interceptions + end end indices::Vector{Int} = Int[] + ky = keys(D[1].attrib) for n = 1:numel(atts) - ky = keys(D[1].attrib) - ((ind = findfirst(ky .== atts[n])) === nothing) && return Int[] + ((ind = findfirst(ky .== atts[n])) === nothing) && continue#return Int[] tf = fill(false, length(D)) for k = 1:length(D) (!isempty(D[k].attrib) && (D[k].attrib[atts[n]] == vals[n])) && (tf[k] = true) end if (n == 1) indices = findall(tf) - else indices = intersect(indices, findall(tf)) + else indices = (dounion > n) ? union(indices, findall(tf)) : intersect(indices, findall(tf)) end end return indices @@ -1945,4 +1974,8 @@ function getbyattrib(D::Vector{<:GMTdataset}; kw...)::Union{Nothing, Vector{GMTd # This is the intended public method. It returns a subset of the selected segments ind = getbyattrib(D, true; kw...) return isempty(ind) ? nothing : D[ind] -end \ No newline at end of file +end + +# --------------------------------------------------------------------------------------------------- +Base.:filter(D::Vector{<:GMTdataset}; kw...) = getbyattrib(D; kw...) +Base.:findall(D::Vector{<:GMTdataset}; kw...) = getbyattrib(D, true; kw...) diff --git a/test/test_common_opts.jl b/test/test_common_opts.jl index afe2c455e..508c04c43 100644 --- a/test/test_common_opts.jl +++ b/test/test_common_opts.jl @@ -276,7 +276,10 @@ GMT.polygonlevels(D, ["a", "b", "c"], [1,2,missing], att="nome"); GMT.edit_segment_headers!(D, [1], "0"); GMT.getbyattrib(D, att="nome", val="a"); - GMT.getbyattrib(D, att=(nome="a", nome2="b")); + filter(D, nome="a", nome2="b"); + filter(D, nome=("a","b")); + findall(D, nome="a"); + info(D); D = mat2ds([0 0; 1 1],["a", "b"]); D.header = "-Wred"; @test GMT.edit_segment_headers!(D, 'W', :get) == "red" @test GMT.edit_segment_headers!(D, 'W', :set, "blue") == "-Wblue" diff --git a/test/test_misc.jl b/test/test_misc.jl index 6fd30137c..7e28c5934 100644 --- a/test/test_misc.jl +++ b/test/test_misc.jl @@ -242,7 +242,7 @@ grdcontour(G, axis="a", color=cpt, pen="+c", fmt=:png, savefig="lixo") D = grdcontour(G, cont=[-2,0,5], dump=true); - show(makecpt(C=:rainbow)) + info(makecpt(C=:rainbow)) add2PSfile("Bla") add2PSfile(["Bla", "Bla"]) From c6ab17ba83afb7764df0b2b5a379071358e9b052 Mon Sep 17 00:00:00 2001 From: Joaquim Date: Tue, 29 Aug 2023 20:41:52 +0100 Subject: [PATCH 3/4] Fix --- src/utils_types.jl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/utils_types.jl b/src/utils_types.jl index 6f1c6a201..1fb9ba5e2 100644 --- a/src/utils_types.jl +++ b/src/utils_types.jl @@ -1930,6 +1930,9 @@ function getbyattrib(D::Vector{<:GMTdataset}, ind_::Bool; kw...)::Vector{Int} (isempty(D[1].attrib)) && (@warn("This datset does not have an `attrib` field and is hence unusable here."); return Int[]) dounion = Int(1e9) # Just a big number if ((_att = find_in_kwargs(kw, [:att :attrib])[1]) !== nothing) # For backward compat. + if !isa(_att, NamedTuple) + ((val = find_in_kwargs(kw, [:val :value])[1]) === nothing) && error("Must provide the `attribute` VALUE.") + end atts, vals = isa(_att, NamedTuple) ? (string.(keys(_att)), string.(values(_att))) : ((string(_att),), (string(val),)) else # FCK unbelievable case. Julia can be f. desparing. It took me an whole afternoon to make this work. From 5b05e387be783e9d8ffcea2641f5d6b9225d1dfb Mon Sep 17 00:00:00 2001 From: Joaquim Date: Tue, 29 Aug 2023 21:15:57 +0100 Subject: [PATCH 4/4] Comment test --- test/test_common_opts.jl | 1 - 1 file changed, 1 deletion(-) diff --git a/test/test_common_opts.jl b/test/test_common_opts.jl index 508c04c43..6ce449eee 100644 --- a/test/test_common_opts.jl +++ b/test/test_common_opts.jl @@ -279,7 +279,6 @@ filter(D, nome="a", nome2="b"); filter(D, nome=("a","b")); findall(D, nome="a"); - info(D); D = mat2ds([0 0; 1 1],["a", "b"]); D.header = "-Wred"; @test GMT.edit_segment_headers!(D, 'W', :get) == "red" @test GMT.edit_segment_headers!(D, 'W', :set, "blue") == "-Wblue"