-
Notifications
You must be signed in to change notification settings - Fork 34
Expand file tree
/
Copy pathgmt_types.jl
More file actions
406 lines (377 loc) · 19.9 KB
/
gmt_types.jl
File metadata and controls
406 lines (377 loc) · 19.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
"""
mutable struct GMTgrid{T<:Number,N} <: AbstractArray{T,N}
The GMTgrid type is how grids, 2D or multi-layered, (geo)referenced or not, communicate in/out
with the GMT and GDAL libraries. They implement the AbstractArray interface.
The fields of this struct are:
- `proj4::String`: Projection string in PROJ4 syntax (Optional)
- `wkt::String`: Projection string in WKT syntax (Optional)
- `epsg::Int`: EPSG code
- `geog::Int`: Is geographic coords? 0 -> No; 1 -> [-180 180]; 2 -> [0 360]
- `range::Vector{Float64}`: 1x6[8] vector with [x_min, x_max, y_min, y_max, z_min, z_max [, v_min, v_max]]
- `inc::Vector{Float64}`: 1x2[3] vector with [x_inc, y_inc [,v_inc]]
- `registration::Int`: Registration type: 0 -> Grid registration; 1 -> Pixel registration
- `nodata::Union{Float64, Float32}`: The value of nodata
- `title::String`: Title (Optional)
- `comment::String`: Remark (Optional)
- `command::String`: Command used to create the grid (Optional)
- `cpt::String`: Name of a recommended GMT CPT name for this grid.
- `names::Vector{String}`: To use whith multi-layered and when layers have names (Optional)
- `x::Vector{Float64}`: [1 x n_columns] vector with XX coordinates
- `y::Vector{Float64}`: [1 x n_rows] vector with YY coordinates
- `v::Union{Vector{<:Real}, Vector{String}}`: [v x n_bands] vector with VV (vertical for 3D grids) coordinates
- `z::Array{T,N}`: [n_rows x n_columns] grid array
- `x_unit::String`: Units of XX axis (Optional)
- `y_unit::String`: Units of YY axis (Optional)
- `v_unit::String`: Units of Vertical axis (Optional)
- `z_unit::String`: Units of z vlues (Optional)
- `layout::String`: A three character string describing the grid memory layout
- `scale::Union{Float64, Float32}=1f0`: When saving in file apply `z = z * scale + offset`
- `offset::Union{Float64, Float32}=0f0`
- `pad::Int=0`: When != 0 means that the array is placed in a padded array of PAD rows/cols
- `hasnans::Int=0`: 0 -> "don't know"; 1 -> confirmed, "have no NaNs"; 2 -> confirmed, "have NaNs"
"""
Base.@kwdef mutable struct GMTgrid{T<:Number,N} <: AbstractArray{T,N}
proj4::String=""
wkt::String=""
epsg::Int=0
geog::Int=0
range::Vector{Float64}=Float64[]#Union{Vector{Float64}, Vector{Any}}=Float64[]
inc::Vector{Float64}=Float64[]#Union{Vector{Float64}, Vector{Any}}=Float64[]
registration::Int=0
nodata::Union{Float64, Float32}=0.0
title::String=""
remark::String=""
command::String=""
cpt::String=""
names::Vector{String}=String[]
x::Array{Float64,1}=Float64[]
y::Array{Float64,1}=Float64[]
v::Union{Vector{<:Real}, Vector{String}, Vector{<:TimeType}}=String[]
z::Array{T,N}=Array{Float64,2}(undef,0,0)
x_unit::String=""
y_unit::String=""
v_unit::String=""
z_unit::String=""
layout::String=""
scale::Union{Float64, Float32}=1f0
offset::Union{Float64, Float32}=0f0
pad::Int=0
hasnans::Int=0
end
Base.size(G::GMTgrid) = size(G.z)
Base.getindex(G::GMTgrid{T,N}, inds::Vararg{Int,N}) where {T,N} = G.z[inds...]
Base.setindex!(G::GMTgrid{T,N}, val, inds::Vararg{Int,N}) where {T,N} = G.z[inds...] = val
Base.BroadcastStyle(::Type{<:GMTgrid}) = Broadcast.ArrayStyle{GMTgrid}()
function Base.similar(bc::Broadcast.Broadcasted{Broadcast.ArrayStyle{GMTgrid}}, ::Type{ElType}) where ElType
G = find4similar(bc.args) # Scan the inputs for the GMTgrid:
GMTgrid(G.proj4, G.wkt, G.epsg, G.geog, G.range, G.inc, G.registration, G.nodata, G.title, G.remark, G.command, G.cpt, G.names, G.x, G.y, G.v, similar(Array{ElType}, axes(bc)), G.x_unit, G.y_unit, G.v_unit, G.z_unit, G.layout, 1f0, 0f0, G.pad, G.hasnans)
end
find4similar(bc::Base.Broadcast.Broadcasted) = find4similar(bc.args)
find4similar(args::Tuple) = find4similar(find4similar(args[1]), Base.tail(args))
find4similar(x) = x
find4similar(::Tuple{}) = nothing
find4similar(G::GMTgrid, rest) = G
find4similar(::Any, rest) = find4similar(rest)
"""
mutable struct GMTimage{T<:Union{Unsigned, Bool}, N} <: AbstractArray{T,N}
The GMTimage type is how images (UInt8, UInt16), 2D or multi-layered, (geo)referenced or not, communicate in/out
with the GMT and GDAL libraries. They implement the AbstractArray interface.
The fields of this struct are:
- `proj4::String`: Projection string in PROJ4 syntax (Optional)
- `wkt::String`: Projection string in WKT syntax (Optional)
- `epsg::Int`: EPSG code
- `geog::Int`: Is geographic coords? 0 -> No; 1 -> [-180 180]; 2 -> [0 360]
- `range::Vector{Float64}`: 1x6[8] vector with [x_min, x_max, y_min, y_max, z_min, z_max [, v_min, v_max]]
- `inc::Vector{Float64}`: 1x2[3] vector with [x_inc, y_inc [,v_inc]]
- `registration::Int`: Registration type: 0 -> Grid registration; 1 -> Pixel registration
- `nodata::Float32`: The value of nodata
- `color_interp::String`: If equal to "Gray" an indexed image with no cmap will get a gray cmap
- `metadata::Vector{String}`: To store any metadata that can eventually be passed to GDAL (Optional)
- `names::Vector{String}`: To use whith multi-band and when bands have names (Optional)
- `x::Vector{Float64}`: [1 x n_columns] vector with XX coordinates
- `y::Vector{Float64}`: [1 x n_rows] vector with YY coordinates
- `v::Vector{Float64}`: [v x n_bands] vector with vertical coords or wavelengths in hypercubes (Optional)
- `image::Array{T,N}`: [n_rows x n_columns x n_bands] image array
- `labels::Vector{String}`: Labels of a Categorical CPT
- `n_colors::Int`: Number of colors stored in the vector 'colormap'
- `colormap::Vector{Int32}`: A vector with n_colors-by-4 saved column-wise
- `alpha::Matrix{UInt8}`: A [n_rows x n_columns] alpha array
- `layout::String`: A four character string describing the image memory layout
- `pad::Int`: When != 0 means that the array is placed in a padded array of PAD rows/cols
"""
Base.@kwdef mutable struct GMTimage{T<:Union{Unsigned, Bool}, N} <: AbstractArray{T,N}
proj4::String=""
wkt::String=""
epsg::Int=0
geog::Int=0
range::Vector{Float64}=Float64[]
inc::Vector{Float64}=Float64[]
registration::Int=0
nodata::Float32=0f0
color_interp::String=""
metadata::Vector{String}=String[]
names::Vector{String}=String[]
x::Vector{Float64}=Float64[]
y::Vector{Float64}=Float64[]
v::Vector{Float64}=Float64[]
image::Array{T,N}=Array{UInt8,2}(undef,0,0)
colormap::Vector{Int32}=Int32[]
labels::Vector{String}=String[] # Labels of a Categorical CPT
n_colors::Int=0
alpha::Matrix{UInt8}=Array{UInt8,2}(undef,0,0)
layout::String=""
pad::Int=0
end
Base.size(I::GMTimage) = size(I.image)
Base.getindex(I::GMTimage{T,N}, inds::Vararg{Int,N}) where {T,N} = I.image[inds...]
Base.setindex!(I::GMTimage{T,N}, val, inds::Vararg{Int,N}) where {T,N} = I.image[inds...] = val
Base.BroadcastStyle(::Type{<:GMTimage}) = Broadcast.ArrayStyle{GMTimage}()
function Base.similar(bc::Broadcast.Broadcasted{Broadcast.ArrayStyle{GMTimage}}, ::Type{ElType}) where ElType
I = find4similar(bc.args) # Scan the inputs for the GMTimage:
GMTimage(I.proj4, I.wkt, I.epsg, I.geog, I.range, I.inc, I.registration, I.nodata, I.color_interp, I.metadata, I.names, I.x, I.y, I.v, similar(Array{ElType}, axes(bc)), I.colormap, I.labels, I.n_colors, I.alpha, I.layout, I.pad)
end
find4similar(I::GMTimage, rest) = I
"""
mutable struct GMTcpt
The fields of this struct are:
- `colormap::Array{Float64,2}`: Mx3 matrix equal to the first three columns of cpt
- `alpha::Array{Float64,1}`: Vector of alpha values. One for each color.
- `range::Array{Float64,2}`: Mx2 matrix with z range for each slice
- `minmax::Array{Float64,1}`: Two elements Vector with zmin,zmax
- `bfn::Array{Float64,2}`: A 3x3(4?) matrix with BFN colors (one per row) in [0 1] interval
- `depth::Cint`: Color depth: 24, 8, 1
- `hinge::Cdouble`: Z-value at discontinuous color break, or NaN
- `cpt::Array{Float64,2}`: Mx6 matrix with r1 g1 b1 r2 g2 b2 for z1 z2 of each slice
- `egorical::Int`: Is this CPT categorical? 0 = No, 1 = Yes, 2 = Yes and keys are strings.
- `label::Vector{String}`: Labels of a Categorical CPT
- `key::Vector{String}`: Keys of a Categorical CPT
- `model::String`: String with color model rgb, hsv, or cmyk [rgb]
- `comment::Vector{String}`: Cell array with any comments
"""
mutable struct GMTcpt
colormap::Array{Float64,2}
alpha::Array{Float64,1}
range::Array{Float64,2}
minmax::Array{Float64,1}
bfn::Array{Float64,2}
depth::Cint
hinge::Cdouble
cpt::Array{Float64,2}
categorical::Int
label::Vector{String}
key::Vector{String}
model::String
comment::Vector{String}
end
GMTcpt() = GMTcpt(Array{Float64,2}(undef,0,0), Vector{Float64}(undef,0), Array{Float64,2}(undef,0,0), Vector{Float64}(undef,0), Array{Float64,2}(undef,0,0), 0, 0.0, Array{Float64,2}(undef,0,0), 0, String[], String[], string(), String[])
Base.size(C::GMTcpt) = size(C.range, 1)
Base.isempty(C::GMTcpt) = (size(C) == 0)
"""
mutable struct GMTps
The fields of this struct are:
- `postscript::String`: Actual PS plot (text string)
- `length::Int`: Byte length of postscript
- `mode::Int`: 1 = Has header, 2 = Has trailer, 3 = Has both
- `comment::Vector{String}`: A vector with any eventual comments
"""
mutable struct GMTps
postscript::String
length::Int
mode::Int
comment::Vector{String}
end
GMTps() = GMTps(string(), 0, 0, String[])
Base.size(P::GMTps) = P.length
Base.isempty(P::GMTps) = (P.length == 0)
"""
mutable struct GMTdataset{T<:Real, N} <: AbstractArray{T,N}
The GMTdataset type is how tables, (geo)referenced or not, communicate in/out with the GMT and GDAL libraries.
They implement the AbstractArray and Tables interface.
The fields of this struct are:
- `data::Array{T,N}`: Mx2 Matrix with segment data
- `ds_bbox::Vector{Float64}`: Global BoundingBox (for when there are many segments)
- `bbox::Vector{Float64}`: Segment BoundingBox
- `attrib::Dict{String, Union{String, Vector{String}}}`: Dictionary with attributes/values (optional)
- `colnames::Vector{String}`: Column names. Antecipate using this with a future Tables inerface
- `text::Vector{String}`: Array with text after data coordinates (mandatory only when plotting Text)
- `header::String`: String with segment header (Optional but sometimes very useful)
- `comment::Vector{String}`: Array with any dataset comments [empty after first segment]
- `proj4::String`: Projection string in PROJ4 syntax (Optional)
- `wkt::String`: Projection string in WKT syntax (Optional)
- `epsg::Int`: EPSG projection code (Optional)
- `geom::Integer`: Geometry type. One of the GDAL's enum (wkbPoint, wkbPolygon, etc...)
"""
Base.@kwdef mutable struct GMTdataset{T<:Real, N} <: AbstractArray{T,N}
data::Array{T,N}=Array{Float64,2}(undef,0,0)
ds_bbox::Vector{Float64}=Float64[]
bbox::Vector{Float64}=Float64[]
attrib::DictSvS=DictSvS()
colnames::Vector{String}=String[]
text::Vector{String}=String[]
header::String=""
comment::Vector{String}=String[]
proj4::String=""
wkt::String=""
epsg::Int=0
geom::Union{UInt32, Int}=0 # 0->Unknown, 1->Point, 2->Line, 3->Polygon, 4->MultiPoint, 5->MultiLine, 6->MultiPolyg
end
Base.size(D::GMTdataset) = size(D.data)
Base.getindex(D::GMTdataset{T,N}, inds::Vararg{Int,N}) where {T,N} = D.data[inds...]
Base.getindex(D::GMTdataset{T,N}, ind::Symbol) where {T,N} = Base.getindex(D, string(ind))
function Base.getindex(D::GMTdataset{T,N}, ind::String) where {T,N}
mat = Tables.getcolumn(D, Symbol(ind))
D2 = mat2ds(mat, colnames=[ind], proj4=D.proj4, wkt=D.wkt)::GMTdataset
if ((Tc = get(D.attrib, "Timecol", "")) != "") # If original has one, try to keep it but may need to recalculate
Tcn = Tables.columnnames(D)[parse.(Int,Tc)] # The Timecol name in input D
i = findfirst(Tables.columnnames(D) .== Tcn)
c = findfirst(Tables.columnnames(D) .== ind)
(i == c) && (D2.attrib = Dict("Timecol" => "$i")) # The selected column was the Time one.
end
D2
end
Base.getindex(D::GMTdataset{T,N}, inds::Vararg{String}) where {T,N} = Base.getindex(D, Symbol.(inds)...)
function Base.getindex(D::GMTdataset{T,N}, inds::Vararg{Symbol}) where {T,N}
# If accessed by column names, create a new GMTdataset.
# Most of this and more should go into a new mat2ds method.
mat = hcat([Tables.getcolumn(D, ind) for ind in inds]...)
colnames_inds = [string.(inds)...] # Because string.(inds) returns a Tuple of strings
D2 = mat2ds(mat, colnames=colnames_inds, proj4=D.proj4, wkt=D.wkt)::GMTdataset
if ((Tc = get(D.attrib, "Timecol", "")) != "") # If original has one, try to keep it but may need to recalculate
Tcn = Tables.columnnames(D)[parse.(Int,Tc)] # The Timecol name in input D
idx = [findfirst(Tables.columnnames(D) .== ind) for ind in colnames_inds] # Find the column numbers of inds
i = findfirst(Tables.columnnames(D) .== Tcn)
itc = (i !== nothing) ? intersect(idx, i) : Int[]
if (!isempty(itc)) # One of the selected columns has a Time column
i = findfirst(idx .== itc) # Find the new column number of the Time column
D2.attrib = Dict("Timecol" => "$i")
end
end
D2
end
#function Base.getindex(D::GMTdataset{T,N}, inds::Vararg) where {T,N}
#length(inds) == 1 && return D.data[inds[1]]
#mat2ds(D, (inds[1],inds[2]))
#end
Base.setindex!(D::GMTdataset{T,N}, val, inds::Vararg{Int}) where {T,N} = D.data[inds...] = val
Base.BroadcastStyle(::Type{<:GMTdataset}) = Broadcast.ArrayStyle{GMTdataset}()
function Base.similar(bc::Broadcast.Broadcasted{Broadcast.ArrayStyle{GMTdataset}}, ::Type{ElType}) where ElType
D = find4similar(bc.args) # Scan the inputs for the GMTdataset:
GMTdataset(D.data, D.ds_bbox, D.bbox, D.attrib, D.colnames, D.text, D.header, D.comment, D.proj4, D.wkt, D.epsg, D.geom)
end
find4similar(D::GMTdataset, rest) = D
GMTdataset(data::Array{Float64,2}, text::Vector{String}) =
GMTdataset(data, Float64[], Float64[], DictSvS(), String[], text, "", String[], "", "", 0, 0)
GMTdataset(data::Array{Float64,2}, text::String) =
GMTdataset(data, Float64[], Float64[], DictSvS(), String[], [text], "", String[], "", "", 0, 0)
GMTdataset(data::Array{Float64,2}) =
GMTdataset(data, Float64[], Float64[], DictSvS(), String[], String[], "", String[], "", "", 0, 0)
GMTdataset(data::Array{Float32,2}, text::Vector{String}) =
GMTdataset(data, Float64[], Float64[], DictSvS(), String[], text, "", String[], "", "", 0, 0)
GMTdataset(data::Array{Float32,2}, text::String) =
GMTdataset(data, Float64[], Float64[], DictSvS(), String[], [text], "", String[], "", "", 0, 0)
GMTdataset(data::Array{Float32,2}) =
GMTdataset(data, Float64[], Float64[], DictSvS(), String[], String[], "", String[], "", "", 0, 0)
"""
struct GMTfv{T<:AbstractFloat} <: AbstractMatrix{T}
The GMTfv struct is used to store a (mostly) triangulated mesh.
The fields of this struct are:
- `verts::Matrix{T}`: A Mx3 Matrix with the data vertices
- `faces::Vector{<:Matrix{<:Int}}`: A vector of matrices with the faces. Each row is a face
- `faces_view::Vector{Matrix{Int}}`: A subset of `faces` with only the visible faces from a certain perspective
- `bbox::Vector{Float64}`: The vertices BoundingBox
- `color::Vector{Vector{String}}`: A vector with G option colors for each face
- `color_vwall::String`: A string for makecpt cmap option argument (e.g. "darkgreen,lightgreen")
- `zscale::Float64`: A multiplicative factor to scale the z values. Default is 1.
- `bfculling::Bool`: If culling of invisible faces is wished. Default is true
- `isflat::Vector{Bool}`: If this is a flat mesh. Default is false
- `proj4::String`: Projection string in PROJ4 syntax (Optional)
- `wkt::String`: Projection string in WKT syntax (Optional)
- `epsg::Int`: EPSG projection code (Optional)
"""
Base.@kwdef mutable struct GMTfv{T<:AbstractFloat} <: AbstractArray{T,2}
verts::Matrix{T}=Matrix{Float64}(undef,0,0)
faces::Vector{<:Matrix{<:Int}}=Vector{Matrix{Int}}(undef,0)
faces_view::Vector{Matrix{Int}}=Vector{Matrix{Int}}(undef,0)
bbox::Vector{Float64}=zeros(6)
color::Vector{Vector{String}}=[String[]]
color_vwall::String=""
zscale::Float64=1.0
bfculling::Bool=true
isflat::Vector{Bool}=[false]
proj4::String=""
wkt::String=""
epsg::Int=0
end
Base.size(FV::GMTfv) = size(FV.verts)
Base.getindex(FV::GMTfv{T}, inds::Vararg{Int}) where {T} = FV.verts[inds...]
Base.setindex!(FV::GMTfv{T}, val, inds::Vararg{Int}) where {T} = FV.verts[inds...] = val
Base.BroadcastStyle(::Type{<:GMTfv}) = Broadcast.ArrayStyle{GMTfv}()
function Base.similar(bc::Broadcast.Broadcasted{Broadcast.ArrayStyle{GMTfv}}, ::Type{ElType}) where ElType
FV = find4similar(bc.args) # Scan the inputs for the FV:
#GMTfv(similar(Array{ElType}, axes(bc)), FV.faces, FV.faces_view, FV.color, FV.bbox, FV.zscale, FV.bfculling, FV.proj4, FV.wkt, FV.epsg)
GMTfv(FV.verts, FV.faces, FV.faces_view, FV.bbox, FV.color, FV.color_vwall, FV.zscale, FV.bfculling, FV.proj4, FV.wkt, FV.epsg)
end
find4similar(FV::GMTfv, rest) = FV
# ------------------------------------------------------------------------------------
mutable struct wrapDatasets
fname::String
ds::GMTdataset
vds::Vector{GMTdataset}
fv::GMTfv
cpt::GMTcpt
function wrapDatasets(arg1, arg2)
td, tvd, tcpt, tfv = GMTdataset(), Vector{GMTdataset}(), GMTcpt(), GMTfv()
if (arg1 !== "") new(arg1, td, tvd, tfv, tcpt)
elseif (isa(arg2, Matrix{<:Real})) new("", mat2ds(arg2), tvd, tfv, tcpt)
elseif (isa(arg2, Vector{<:Real})) new("", mat2ds(arg2), tvd, tfv, tcpt)
elseif (isa(arg2, GMTdataset)) new("", arg2, tvd, tfv, tcpt)
elseif (isa(arg2, Vector{<:GMTdataset})) new("", td, arg2, tfv, tcpt)
elseif (isa(arg2, GMTfv)) new("", td, tvd, arg2, tcpt)
elseif (isa(arg2, GMTcpt)) new("", td, tvd, tfv, arg2)
elseif (arg1 === "" && arg2 === nothing) new("", td, tvd, tfv, tcpt) # Less usual case in plot where only kwargs are given
else error("Unknown types ($(typeof(arg1)), $(typeof(arg2))) in wrapDatasets")
end
end
end
function unwrapDatasets(w::wrapDatasets)
return w.fname, !isempty(w.ds) ? w.ds : !isempty(w.vds) ? w.vds : !isempty(w.fv) ? w.fv : !isempty(w.cpt) ? w.cpt : nothing
end
# ------------------------------------------------------------------------------------
mutable struct wrapGrids
fname::String
grd::GMTgrid
img::GMTimage
function wrapGrids(arg1, arg2)
tg, ti = GMTgrid(), GMTimage()
if (arg1 !== "") new(arg1, tg, ti)
elseif (isa(arg2, GMTgrid)) new("", arg2, ti)
elseif (isa(arg2, GMTimage)) new("", tg, arg2)
elseif (isa(arg2, Matrix{<:Real})) new("", mat2grid(arg2), ti)
elseif (arg1 === "" && arg2 === nothing) new("", tg, ti) # Less usual case in grdlandmask where only kwargs are given
else error("Unknown types ($(typeof(arg1)), $(typeof(arg2))) in wrapGrids")
end
end
end
function unwrapGrids(w::wrapGrids)
return w.fname, !isempty(w.grd) ? w.grd : !isempty(w.img) ? w.img : nothing
end
#=
Base.@kwdef struct GMTtypes
stored::String = ""
grd::GMTgrid = GMTgrid()
img::GMTimage = GMTimage()
ds::GMTdataset = GMTdataset()
dsv::Vector{GMTdataset::Vector{GMTdataset{Float64, 2}}} = [GMTdataset()]
cpt::GMTcpt = GMTcpt()
ps::GMTps = GMTps()
function GMTtypes(stored, grd, img, ds, dsv, cpt, ps)
stored = (!isempty(grd)) ? "grd" : (!isempty(img)) ? "img" : (!isempty(ds)) ? "ds" : (!isempty(dsv)) ? "dsv" : (!isempty(cpt)) ? "cpt" : (!isempty(ps)) ? "ps" : ""
new(stored, grd, img, ds, dsv, cpt, ps)
end
end
=#
struct WrapperPluto fname::String end
const global GItype = Union{GMTgrid, GMTimage}
const global GDtype = Union{GMTdataset, Vector{<:GMTdataset}}
#function meta(D::GMTdataset; kw...)
#end