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
14 changes: 10 additions & 4 deletions ext/DFGPlots.jl
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,20 @@ function plotDFG(dfg::GraphsDFG; p::DFGPlotProps = DFGPlotProps(), interactive::
0;
text = "",
font = :bold,
fontsize = 30,
fontsize = 20,
glowcolor = (:white, 1),
glowwidth = 3,
)

ax.aspect = GraphMakie.DataAspect()
ax.aspect = nothing
ax.autolimitaspect = 1
if interactive
node_hover_labels = map(dfg.g.labels) do label
tags = sort(DFG.listTags(dfg, label))
tags_str = isempty(tags) ? "[]" : "[" * join(string.(tags), ", ") * "]"
return string(label, "\ntags: ", tags_str)
end

function node_drag_action(state, idx, event, axis)
p[:node_pos][][idx] = event.data
return p[:node_pos][] = p[:node_pos][]
Expand All @@ -79,8 +86,7 @@ function plotDFG(dfg::GraphsDFG; p::DFGPlotProps = DFGPlotProps(), interactive::
GraphMakie.register_interaction!(ax, :ndrag, ndrag)

function node_hover_action(state, idx, event, axis)
label = dfg.g.labels[idx]
label_text.text[] = state ? string(label) : ""
label_text.text[] = state ? node_hover_labels[idx] : ""
return label_text.transformation.translation[] = (event.data..., 0)
end
nhover = NodeHoverHandler(node_hover_action)
Expand Down
6 changes: 4 additions & 2 deletions src/FileDFG/services/FileDFG.jl
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ function loadDFG!(

# extract the factor graph from fileDFG folder
variablefiles = readdir(joinpath(loaddir, "variables"); sort = false, join = true)
sort!(variablefiles; lt = natural_lt)

# type instability on `variables` as either `::Vector{Variable}` or `::Vector{VariableDFG{<:}}` (vector of abstract)
variables = @showprogress dt = 1 desc = "loading variables" asyncmap(
Expand All @@ -129,6 +130,7 @@ function loadDFG!(
@debug "Loaded $(length(variables)) variables"

factorfiles = readdir(joinpath(loaddir, "factors"); sort = false, join = true)
sort!(factorfiles; lt = natural_lt)

factors = @showprogress dt = 1 desc = "loading factors" asyncmap(factorfiles) do file
f = JSON.parsefile(file, F; style = DFGJSONStyle())
Expand Down Expand Up @@ -203,14 +205,14 @@ function loadDFG(file::AbstractString)
blobproviders = if isfile(joinpath(loaddir, "blobproviders.json"))
JSON.parsefile(
joinpath(loaddir, "blobproviders.json"),
Dict{Symbol, AbstractBlobprovider};
OrderedDict{Symbol, AbstractBlobprovider};
style = DFGJSONStyle(),
)
elseif isfile(joinpath(loaddir, "blobstores.json"))
# backward compat: load old blobstores.json format
JSON.parsefile(
joinpath(loaddir, "blobstores.json"),
Dict{Symbol, AbstractBlobprovider};
OrderedDict{Symbol, AbstractBlobprovider};
style = DFGJSONStyle(),
)
else
Expand Down
24 changes: 24 additions & 0 deletions src/GraphsDFG/FactorGraphs/FactorGraphs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import Graphs:
add_vertex!,
add_edge!,
rem_vertex!,
rem_vertices!,
rem_edge!,
has_vertex,
has_edge,
Expand Down Expand Up @@ -171,4 +172,27 @@ function rem_vertex!(g::FactorGraph{T, V, F}, v::Integer) where {T, V, F}
return true
end

function Graphs.rem_vertices!(g::FactorGraph{T, V, F}, vs::Vector{Int}) where {T, V, F}
for v in sort(vs; rev = true)
v in vertices(g) || continue
lastv = nv(g)

rem_vertex!(g.graph, v) || continue

label = g.labels[v]
delete!(g.variables, label)
delete!(g.factors, label)

if v != lastv
g.labels[v] = g.labels[lastv] #lastSym
else
delete!(g.labels, v)
end
end

OrderedCollections.rehash!(g.variables)
OrderedCollections.rehash!(g.factors)
return true
end

end
7 changes: 3 additions & 4 deletions src/GraphsDFG/services/factor_ops.jl
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,9 @@ function DFG.deleteFactor!(dfg::GraphsDFG, label::Symbol)
end

function DFG.deleteFactors!(dfg::AbstractDFG, labels::Vector{Symbol})
counts = asyncmap(labels) do l
return deleteFactor!(dfg, l)
end
return sum(counts)
count = sum(map(l->hasFactor(dfg, l), labels); init = 0)
rem_vertices!(dfg.g, map(l->dfg.g.labels[l], labels))
return count
end

function DFG.deleteFactors!(dfg::AbstractDFG; kwargs...)
Expand Down
15 changes: 14 additions & 1 deletion src/GraphsDFG/services/variable_ops.jl
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,25 @@ function DFG.deleteVariable!(dfg::GraphsDFG, label::Symbol)#::Tuple{AbstractGrap
!haskey(dfg.g.variables, label) && return 0

# orphaned factors are not supported.
del_facs = map(l -> deleteFactor!(dfg, l), listNeighbors(dfg, label))
del_facs = deleteFactors!(dfg, listNeighbors(dfg, label))

rem_vertex!(dfg.g, dfg.g.labels[label])
return sum(del_facs; init = 0) + 1
end

function DFG.deleteVariables!(dfg::GraphsDFG, labels::Vector{Symbol})
# collect factor neighbors for all variables before any deletion
fac_labels = mapreduce(l -> listNeighbors(dfg, l), union, labels; init = Symbol[])
fac_labels = filter(l -> hasFactor(dfg, l), fac_labels)

var_labels = filter(l -> hasVariable(dfg, l), labels)

count = length(var_labels) + length(fac_labels)
vs = map(l -> dfg.g.labels[l], [var_labels; fac_labels])
rem_vertices!(dfg.g, vs)
return count
end

function DFG.listVariables(
dfg::GraphsDFG;
whereSolvable::Union{Nothing, Function} = nothing,
Expand Down
30 changes: 15 additions & 15 deletions src/entities/Error.jl
Original file line number Diff line number Diff line change
Expand Up @@ -44,41 +44,41 @@ function Base.showerror(io::IO, ex::LabelExistsError)
end

"""
IdNotFoundError(Id, available)
IdNotFoundError(id, available)

Error thrown when a requested Id is not found.
Error thrown when a requested id is not found.
"""
struct IdNotFoundError <: Exception
struct IdNotFoundError{T} <: Exception
name::String
Id::UUID
available::Vector{UUID}
id::T
available::Vector{T}
end

IdNotFoundError(name::String, Id::UUID) = IdNotFoundError(name, Id, UUID[])
IdNotFoundError(Id::UUID) = IdNotFoundError("Node", Id, UUID[])
IdNotFoundError(name::String, id::T) where {T} = IdNotFoundError(name, id, T[])
IdNotFoundError(id::T) where {T} = IdNotFoundError("Node", id, T[])

function Base.showerror(io::IO, ex::IdNotFoundError)
print(io, "IdNotFoundError: ", ex.name, " Id '", ex.Id, "' not found.")
print(io, "IdNotFoundError: ", ex.name, " id '", ex.id, "' not found.")
if !isempty(ex.available)
println(io, " Available Ids:")
println(io, " Available ids:")
show(io, ex.available)
end
end

"""
IdExistsError(Id)
IdExistsError(id)

Error thrown when attempting to add an Id that already exists in the collection.
Error thrown when attempting to add an id that already exists in the collection.
"""
struct IdExistsError <: Exception
struct IdExistsError{T} <: Exception
name::String
Id::UUID
id::T
end

IdExistsError(Id::UUID) = IdExistsError("Node", Id)
IdExistsError(id) = IdExistsError("Node", id)

function Base.showerror(io::IO, ex::IdExistsError)
return print(io, "IdExistsError: ", ex.name, " Id '", ex.Id, "' already exists.")
return print(io, "IdExistsError: ", ex.name, " id '", ex.id, "' already exists.")
end

"""
Expand Down
2 changes: 1 addition & 1 deletion src/services/variable_ops.jl
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ function deleteVariables!(dfg::AbstractDFG, labels::Vector{Symbol})
counts = asyncmap(labels) do l
return deleteVariable!(dfg, l)
end
return sum(counts)
return sum(counts; init = 0)
end

function deleteVariables!(dfg::AbstractDFG; kwargs...)
Expand Down
17 changes: 11 additions & 6 deletions test/testBlocks.jl
Original file line number Diff line number Diff line change
Expand Up @@ -460,15 +460,20 @@ function VariablesandFactorsCRUD_SET!(fg, v1, v2, v3, f0, f1, f2)
@test addVariable!(fg, v3) === v3
@test addFactor!(fg, f2) === f2

@test deleteFactor!(fg, f2) == 1
@test deleteFactors!(fg, [getLabel(f2)]) == 1
@test addFactor!(fg, f2) === f2
@test deleteFactors!(fg; whereLabel = ==(string(getLabel(f2)))) == 1
@test deleteFactors!(fg; whereLabel = ==("doesnotexist")) == 0

@test addFactor!(fg, f2) === f2
@test deleteVariables!(fg, [getLabel(v3)]) == 2
@test addVariable!(fg, v3) === v3
@test deleteVariables!(fg; whereLabel = ==(string(getLabel(v3)))) == 1
@test deleteVariables!(fg; whereLabel = ==("doesnotexist")) == 0

@test deleteFactor!(fg, f2) == 0
@test lsf(fg) == [:abf1]

delvarCompare = getVariable(fg, :c)
delfacCompare = []
ndel = deleteVariable!(fg, v3)
@test ndel == 1

@test getVariable(fg, :a) == v1

@test addFactor!(fg, f0) == f0
Expand Down
Loading