Public API
These are the functions and types exported by AdriaArrayGeometryPicker (plus the two accessors columns and metadata, which are not exported because their names are common).
The picker window
AdriaArrayGeometryPicker.geometry_picker Function
geometry_picker(; wait = !isinteractive(), save = nothing) -> NamedTuple
geometry_picker(path::AbstractString; wait = !isinteractive(), save = nothing) -> NamedTupleOpen the AdriaArray geometry picker window.
Without arguments, the window opens empty; load a profile with "Load Profile" in the menu.
With
path, the file is opened right away. It is recognised by its content:a GUI state file (
.aagps, seesave_gui_state; a JLD2 file whose entry"format"is"AdriaArrayGeometryPicker state", or"MakiePickerGUI state"for files of MakiePickerGUI.jl) is restored withload_gui_state!: the profile it refers to is loaded and the settings and picks are applied;every other file is loaded as a GeophysicalModelGenerator profile (
.pgmg, seeopen_profile!).
An
ArgumentErroris thrown ifpathdoes not exist.
The window has a dropdown menu ("Load Profile", "Save State", "Load State", "Save Picks", "Load Picks", "Load Compare Picks", "Save Screenshot", "Close"; see menu_selection), collapsible panels for the volume, surface, point and topography data, compared picks, a map overview and screenshots, and picking in the profile axis while the "Picking" toggle is on: A + click adds a pick, D + click removes one, click and drag moves one.
Keywords
wait: block until the window is closed. The default waits when Julia runs a script or a command (julia -e ...) and returns right away in the REPL, so the process does not end while the window is open.save: path of a PNG file. If given, the window is rendered offscreen into that file (after the filepathis loaded) instead of being shown, and the function returns without waiting (e.g. for documentation images or headless tests).
Returns
The session, a NamedTuple with the figure (fig), the profile Observable, profile_file and profile_path, the panels, axes and widgets of picker_layout, the picking state picking (see picking_state), the plot states (volume, surface, points, topography, topomap, compare) and the GLMakie screen. It is what current_picks, set_picks!, save_gui_state and load_gui_state! take.
Examples
using AdriaArrayGeometryPicker
# 1) an empty window
session = geometry_picker()
# 2) a window with a profile
session = geometry_picker(joinpath(pkgdir(AdriaArrayGeometryPicker), "assets", "Profile1.pgmg"))
# 3) a window with a saved state (profile, settings and picks)
session = geometry_picker("my_state.aagps")
# offscreen: render the window with a profile into a PNG file
geometry_picker("profile.pgmg"; save = "picker.png")From the command line (blocks until the window is closed):
julia --project -e "using AdriaArrayGeometryPicker; geometry_picker(\"profile.pgmg\")"Picks
AdriaArrayGeometryPicker.Picks Type
Picks(points; names = (:x, :y), columns = (;), metadata = Dict{String,Any}())
Picks(x, y; kwargs...)A single set of picked points. Generic: independent of Makie and of the profile data, so it can be used for file IO (save_picks, load_picks), tests and post-processing without a GUI.
Arguments
points: vector of 2D points. Anything with at least two indexable coordinates is accepted (Point2f,Point3f,Point3das in the picks of the GUI, tuples, vectors); only the first two coordinates are kept.x,y: alternatively, the two coordinates as vectors of equal length.
Keywords
names: names of the two coordinates, used as column names in files (e.g.(:x, :depth)).columns: additional per-point columns as aNamedTupleof vectors of the same length aspoints(e.g.(lat = ..., lon = ...)); their names must differ fromnames.metadata: free-form information such as user name, date, units or profile information (keys are converted to strings).
Picks supports length, isempty, collect (a copy of the points), == and the accessors points, columns and metadata.
Example
julia> p = Picks([(0.0, -10.0), (50.0, -35.0)]; names = (:x, :depth),
columns = (lat = [45.0, 45.5],), metadata = Dict("user" => "MT"))
Picks(2 points, names = (:x, :depth), columns = (:lat,))
julia> length(p)
2
julia> Picks([0.0, 50.0], [-10.0, -35.0]; names = (:x, :depth)) == Picks([(0.0, -10.0), (50.0, -35.0)]; names = (:x, :depth))
trueAdriaArrayGeometryPicker.points Function
points(p::Picks) -> Vector{Point2{Float64}}The picked points as a vector of 2D points (the stored vector, not a copy).
Example
julia> p = Picks([(0.0, -10.0), (50.0, -35.0)]);
julia> [Tuple(q) for q in points(p)]
2-element Vector{Tuple{Float64, Float64}}:
(0.0, -10.0)
(50.0, -35.0)AdriaArrayGeometryPicker.columns Function
columns(p::Picks) -> NamedTupleAll per-point data as a table-like NamedTuple: the two coordinates (named according to p.names) followed by the extra columns. This is what is written to files.
Example
julia> p = Picks([(0.0, -10.0), (50.0, -35.0)]; names = (:x, :depth), columns = (lat = [45.0, 45.5],));
julia> columns(p)
(x = [0.0, 50.0], depth = [-10.0, -35.0], lat = [45.0, 45.5])AdriaArrayGeometryPicker.metadata Function
metadata(p::Picks) -> Dict{String,Any}The metadata dictionary (the stored one, so it can be modified in place).
Example
julia> p = Picks([(0.0, -10.0)]; metadata = Dict("user" => "MT"));
julia> metadata(p)["date"] = "2024-01-01";
julia> metadata(p)["user"], metadata(p)["date"]
("MT", "2024-01-01")AdriaArrayGeometryPicker.save_picks Function
save_picks(path, picks; extra = nothing, format = nothing, delim = ',') -> StringSave picks (a Picks or a vector of points) to path and return the path written.
The file format is taken from the extension (.aagpp, a JLD2 file, or .csv) unless format (:jld2 or :csv) is given. A path without extension gets .aagpp appended. .jld2 is accepted as well (pick files of older versions).
extra is an optional function points -> NamedTuple that computes additional columns at save time, e.g. geographic coordinates of points picked on a profile:
p = Picks([(0.0, -10.0), (50.0, -35.0)]; names = (:x, :depth))
lon_at(x) = 10 + x / 100 # e.g. an interpolation along the profile
save_picks("picks.csv", p; extra = pts -> (lon = lon_at.(first.(pts)),))CSV files store metadata as text in # comment lines, so non-string metadata values come back as strings from load_picks. JLD2 files keep all Julia types. Generic.
Arguments
path: output file.picks: aPicks, or a vector of points (which is converted withPicks(points)).
Keywords
extra: functionpoints -> NamedTuplethat returns additional columns (vectors with one value per point), see above.format::jld2or:csv(default: from the extension ofpath).delim: column delimiter of CSV files.
Example
Round trip through a JLD2 and a CSV file:
julia> p = Picks([(0.0, -10.0), (50.0, -35.0)]; names = (:x, :depth),
metadata = Dict("user" => "MT"));
julia> mktempdir() do dir
[load_picks(save_picks(joinpath(dir, name), p)) == p for name in ("picks.aagpp", "picks.csv")]
end
2-element Vector{Bool}:
1
1AdriaArrayGeometryPicker.load_picks Function
load_picks(path; format = nothing, delim = ',') -> PicksLoad picks from a .aagpp (JLD2) or .csv file; .jld2 files of older versions are read too.
Supported inputs:
files written by
save_picks(also those of MakiePickerGUI.jl)pick files of the original AdriaArrayGeometryPicker.jl (JLD2 with
picks,pick_info,profile_info);pick_infoentries become metadata (user_nameis stored as"user"), all other entries are stored under their own keyplain CSV files with or without header row; the first two columns are the coordinates
Arguments
path: the file to read; anArgumentErroris thrown if it does not exist.
Keywords
format::jld2or:csv(default: from the extension ofpath).delim: column delimiter of CSV files.
Returns a Picks. Generic.
Example
julia> p = Picks([(0.0, -10.0), (50.0, -35.0)]; names = (:x, :depth),
columns = (lat = [45.0, 45.5],));
julia> q = mktempdir() do dir
load_picks(save_picks(joinpath(dir, "picks.csv"), p))
end
Picks(2 points, names = (:x, :depth), columns = (:lat,))
julia> q == p
truePicks and state of a window
AdriaArrayGeometryPicker.current_picks Function
current_picks(session) -> PicksThe picks of the GUI as a Picks with the coordinates (:x, :depth), the columns lon and lat (interpolated from the profile, see pick_lonlat) and the metadata user (the name in the user name field), date, profile_file, profile_type ("vertical" or "horizontal") and the start / end coordinates of the profile. On a horizontal slice the picks are made in the lon/lat plane: x is NaN, depth is the depth of the slice, lon and lat are the picked position, and the metadata hold the depth of the slice instead of the start / end coordinates.
Arguments
session: aNamedTuple(or any object with these properties); thesessionof the picker (seemenu_selection) has them all:profile(required): theObservablethat holds the profile,picking(required): the picking state ofpicking_state,profile_file(optional):Observablewith the name of the profile file (default""),widgets.pick_name(optional): the user nameTextbox(default user:"").
A custom GUI only needs e.g. session = (; profile, picking). Requires a GeophysicalModelGenerator ProfileData (or nothing, then lon and lat are NaN).
Returns the Picks.
Example
fig = Figure()
area = profile_plot_area!(fig[1, 1])
pick_name = Textbox(fig[2, 1]; placeholder = "User name")
profile = Observable{Any}(nothing)
profile_file = Observable("")
picking = picking_state(fig, profile, area.profile)
session = (; profile, profile_file, picking, widgets = (; pick_name))
open_profile!(session, joinpath(pkgdir(AdriaArrayGeometryPicker), "assets", "Profile1.pgmg"))
set_pick_points!(picking, [(100.0, -50.0), (250.0, -120.0)])
set_text!(pick_name, "MT")
p = current_picks(session) # columns x, depth, lon, lat; metadata user = "MT", ...
save_picks("picks.csv", p)AdriaArrayGeometryPicker.set_picks! Function
set_picks!(session, picks::Picks) -> BoolShow picks as the (editable) picks of the GUI. Picks that were made on the other type of profile (vertical or horizontal, see the metadata profile_type; files that do not say are vertical) are not loaded: the function warns and returns false, as it does without a loaded profile. Picks of another profile of the same type (other start / end point or slice depth) are taken over with a warning below the "Picking" label (widgets.pick_warning, if the session has it) and in the log; saving them assigns them to the current profile, user and time (see current_picks), on a horizontal slice also the depth of the loaded slice. Returns true if the picks belong to the loaded profile, false if not (see picks_match_profile). The user name of the picks is put into the user name field if that is empty. On a horizontal slice the picks are shown at their lon / lat columns.
Arguments
session: as forcurrent_picks:profileandpickingare required,widgets.pick_nameis optional (without it the user name is not shown).picks: thePicks, e.g. fromload_picks.
Requires a GeophysicalModelGenerator ProfileData.
AdriaArrayGeometryPicker.save_gui_state Function
save_gui_state(path, session) -> Union{String,Nothing}Save the state of the GUI to the file path (.aagps is appended if there is no extension; the content is a JLD2 file, written with jldopen, which accepts any extension): the path of the loaded profile file and the settings (see gui_settings). The profile data itself is not stored, it is loaded again from its file by load_gui_state!. Requires a GeophysicalModelGenerator ProfileData to be loaded.
Arguments
path: output file.session: as forgui_settings, plus the fieldprofile_path(anObservable{String}with the path of the loaded profile file, set byopen_profile!).
Returns the path written, or nothing (and warns) if no profile file is known (session.profile_path[] is empty, e.g. because the profile was loaded with load_profile! instead of open_profile!).
AdriaArrayGeometryPicker.load_gui_state! Function
load_gui_state!(session, path) -> Union{typeof(session),Nothing}Restore a GUI state saved by save_gui_state: load the profile file it refers to with open_profile! and apply the saved settings with apply_settings! (only the parts that the session has). Requires a GeophysicalModelGenerator ProfileData file.
Arguments
session: as forgui_settings;profileis required,profile_fileandprofile_pathare set if present (seeopen_profile!).path: a file written bysave_gui_state(.aagps; or a.jld2state file of MakiePickerGUI.jl, format"MakiePickerGUI state"). The file is recognised by its content, not by its extension.
Returns session; nothing is changed (and nothing is returned) if the profile file no longer exists. Throws an error if path is not a state file.