Skip to content

Commit 3201b6c

Browse files
authored
Standardize more types, filters, and more cleanup (#1163)
1 parent e8b1286 commit 3201b6c

38 files changed

+1232
-1010
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ docs/build
77
Manifest.toml
88
dev
99
test/sandbox.jl
10+
lcov.info

NEWS.md

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,19 @@ Listing news on any major breaking changes in DFG. For regular changes, see int
22
# v0.28
33
- Reading or deserialzing of factor graphs created prior to v0.25 are no longer suppoted with the complete removal of User/Robot/Session
44
- Deprecated AbstractRelativeMinimize and AbstractManifoldsMinimize
5-
6-
#TODO pending:
7-
- AbstractPrior -> AbstractPriorObservation/PriorObservation
8-
- AbstractRelative -> RelativeObservation/RelativeObservation
9-
- InferenceType -> AbstractPackedFactorObservation
10-
- InferenceVariable -> [Abstract]VariableStateType/AbstractVarstateType
11-
- PackedSamplableBelief -> [Abstract]PackedBelief
5+
- Rename `VariableState` -> `State`
6+
7+
Abstract Types Standardized, see #1153:
8+
- AbstractParams -> [Abstract]DFGParams
9+
- DFGNode -> [Abstract]GraphNode
10+
- AbstractDFGVariable -> [Abstract]GraphVariable
11+
- AbstractDFGFactor -> [Abstract]GraphFactor
12+
- AbstractPackedFactorObservation -> [Abstract]PackedObservation
13+
- AbstractFactorObservation -> [Abstract]Observation
14+
- AbstractPrior -> [Abstract]PriorObservation
15+
- AbstractRelative -> [Abstract]RelativeObservation
16+
- FactorSolverCache -> [Abstract]FactorCache
17+
- VariableStateType -> [Abstract]StateType
1218

1319
# v0.27
1420
- `delete` returns number of nodes deleted and no longer the object that was deleted.

docs/src/DrawingGraphs.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,8 @@ More information at [GraphMakie.jl](https://github.com/MakieOrg/GraphMakie.jl)
6464
Dot files are a standard format for visualizing graphs and applications such as
6565
xdot are available to view the files. Dot plotting does not require `GraphMakie`
6666
and can be drawn by either:
67-
- Calling [`toDot`](@ref) on any graph to produce a string of the graph
68-
- Calling [`toDotFile`](@ref) on any graph to save it directly to a dotfile
67+
- Calling [`DFG.toDot`](@ref) on any graph to produce a string of the graph
68+
- Calling [`DFG.toDotFile`](@ref) on any graph to save it directly to a dotfile
6969

7070
```julia
7171
using DistributedFactorGraphs

docs/src/GraphData.md

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ The following is a guideline to using these parameters.
1515

1616
**NOTE**: Adds in general throw an error if the element already exists. Update will update the element if it exists, otherwise it will add it.
1717

18-
**NOTE**: In general these functions will return an error if the respective element is not found. This is to avoid returning, say, nothing, which will be horribly confusing if you tried `getVariableState(dfg, :a, :b)` and it returned nothing - which was missing, :a or :b, or was there a communication issue? We recommend coding defensively and trapping errors in critical portions of your user code.
18+
**NOTE**: In general these functions will return an error if the respective element is not found. This is to avoid returning, say, nothing, which will be horribly confusing if you tried `getState(dfg, :a, :b)` and it returned nothing - which was missing, :a or :b, or was there a communication issue? We recommend coding defensively and trapping errors in critical portions of your user code.
1919

2020
**NOTE**: All data is passed by reference, so if you update the returned structure it will update in the graph. The database driver is an exception, and once the variable or factor is updated you need to call update* to persist the changes to the graph.
2121

@@ -53,7 +53,7 @@ Each variable or factor can have a timestamp associated with it.
5353

5454
Tags are a set of symbols that contain identifiers for the variable or factor.
5555

56-
- [`listTags`](@ref)
56+
- [`getTags`](@ref)
5757
- [`mergeTags!`](@ref)
5858
- [`removeTags!`](@ref)
5959
- [`emptyTags!`](@ref)
@@ -118,41 +118,41 @@ updatePPE!(dfg, :x0, ppe, :default)
118118
updatePPE!(dfg, [x0], :default)
119119
```
120120

121-
#### Solver Data
121+
#### Variable States (Solver Data)
122122

123-
Solver data is used by IncrementalInference/RoME/Caesar solver to produce the above PPEs.
123+
Variable `State`s are used by the IncrementalInference/RoME/Caesar solver.
124124

125125
Related functions:
126126

127127

128-
- [`listVariableStates`](@ref)
129-
- [`getVariableState`](@ref)
130-
- [`addVariableState!`](@ref)
131-
- [`mergeVariableState!`](@ref)
132-
- [`deleteVariableState!`](@ref)
133-
- [`mergeVariableState!`](@ref)
128+
- [`listStates`](@ref)
129+
- [`getState`](@ref)
130+
- [`addState!`](@ref)
131+
- [`mergeState!`](@ref)
132+
- [`deleteState!`](@ref)
133+
- [`mergeState!`](@ref)
134134

135135

136-
Example of solver data operations:
136+
Example of variable `State` operations:
137137

138138
```julia
139139
# Add new VND of type ContinuousScalar to :x0
140-
# Could also do VariableState(ContinuousScalar())
141-
vnd = VariableState{ContinuousScalar}()
142-
addVariableState!(dfg, :x0, vnd, :parametric)
143-
@show listVariableStates(dfg, :x0)
140+
# Could also do State(ContinuousScalar())
141+
state = State{ContinuousScalar}()
142+
addState!(dfg, :x0, state, :parametric)
143+
@show listStates(dfg, :x0)
144144
# Get the data back - note that this is a reference to above.
145-
vndBack = getVariableState(dfg, :x0, :parametric)
145+
stateBack = getState(dfg, :x0, :parametric)
146146
# Delete it
147-
deleteVariableState!(dfg, :x0, :parametric)
147+
deleteState!(dfg, :x0, :parametric)
148148
```
149149

150-
#### Small Data
150+
#### Metadata
151151

152-
Small data allows you to assign a dictionary to variables. It is a useful way to
153-
keep small amounts of string data in a variable. As it is stored in the graph
152+
Metadata (small data) allows you to assign a dictionary to variables. It is a useful way to
153+
keep small amounts of primative (Strings, Integers, Floats, Bool) data in a variable. As it is stored in the graph
154154
itself, large entries will slow the graph down, so if data should exceed a
155-
few bytes/kb, it should rather be saved in bigData.
155+
few bytes/kb, it should rather be saved in Blobs.
156156

157157

158158
- [`getMetadata`](@ref)

src/Common.jl

Lines changed: 62 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@
33
_getmodule(t::T) where {T} = T.name.module
44
_getname(t::T) where {T} = T.name.name
55

6-
function convertPackedType(t::Union{T, Type{T}}) where {T <: AbstractFactorObservation}
6+
function convertPackedType(t::Union{T, Type{T}}) where {T <: AbstractObservation}
77
return getfield(_getmodule(t), Symbol("Packed$(_getname(t))"))
88
end
9-
function convertStructType(::Type{PT}) where {PT <: AbstractPackedFactorObservation}
9+
function convertStructType(::Type{PT}) where {PT <: AbstractPackedObservation}
1010
# see #668 for expanded reasoning. PT may be ::UnionAll if the type is of template type.
1111
ptt = PT isa DataType ? PT.name.name : PT
1212
moduleName = PT isa DataType ? PT.name.module : Main
@@ -64,11 +64,68 @@ Related
6464
6565
ls, lsf
6666
"""
67-
function sortDFG(vars::Vector{<:DFGNode}; by = getTimestamp, kwargs...)
67+
function sortDFG(vars::Vector{<:AbstractGraphNode}; by = getTimestamp, kwargs...)
6868
return sort(vars; by = by, kwargs...)
6969
end
7070
sortDFG(vars::Vector{Symbol}; lt = natural_lt, kwargs...) = sort(vars; lt = lt, kwargs...)
7171

72+
##==============================================================================
73+
## Filtering
74+
##==============================================================================
75+
76+
# std_numeric_predicates = [==, <, <=, >, >=, in]
77+
# std_string_predicates = [==, in, contains, startswith, endswith]
78+
79+
# # full list
80+
# tags_includes(tag::Symbol) = Base.Fix1(in, tag)
81+
# solvable_eq(x::Int) = ==(x)
82+
# solvable_in(x::Vector{Int}) = in(x)
83+
# solvable_lt(x::Int) = <(x)
84+
# solvable_lte(x::Int) = <=(x)
85+
# solvable_gt(x::Int) = >(x)
86+
# solvable_gte(x::Int) = >=(x)
87+
# label_in(x::Vector{Symbol}) = in(x)
88+
# label_contains(x::String) = contains(x)
89+
# label_startswith(x::String) = startswith(x)
90+
# label_endswith(x::String) = endswith(x)
91+
# type_eq(x::AbstractStateType) = ==(x)
92+
# type_in(x::Vector{<:AbstractStateType}) = in(x)
93+
# type_contains(x::String) = contains(x)
94+
# type_startswith(x::String) = startswith(x)
95+
# type_endswith(x::String) = endswith(x)
96+
97+
# Set predicates
98+
# collection_includes(item) = Base.Fix1(in, item) # collection includes item (item in collection)
99+
100+
# not supported helper
101+
# collection_overlap(collection) = !isdisjoint(collection) # collection overlaps with another collection
102+
103+
"""
104+
$SIGNATURES
105+
Filter nodes in a DFG based on a predicate function.
106+
This function modifies the input `nodes` vector in place, removing nodes that do not satisfy the predicate.
107+
108+
- **For cross-backend compatibility:**
109+
Use only the standard predicates (`==`, `<`, `<=`, `>`, `>=`, `in`, `contains`, `startswith`, `endswith`)
110+
when you need your code to work with both in-memory and database-backed DFGs.
111+
These are likely to be supported by database query languages and are defined in `std_numeric_predicates` and `std_string_predicates`.
112+
113+
- **For in-memory only operations:**
114+
You can use any Julia predicate, since you have full access to the data and Julia's capabilities.
115+
This is more flexible but will not work if you later switch to a database backend or another programming language.
116+
117+
Standard predicates
118+
- Numeric predicates: `==`, `<`, `<=`, `>`, `>=`, `in`
119+
- String predicates: `==`, `contains`, `startswith`, `endswith`, `in`
120+
"""
121+
function filterDFG! end
122+
123+
filterDFG!(nodes, predicate::Nothing, by::Function = identity) = nodes
124+
# function filterDFG!(nodes, predicate::Base.Fix2, by=identity)
125+
function filterDFG!(nodes, predicate::Function, by::Function = identity)
126+
return filter!(predicate by, nodes)
127+
end
128+
72129
##==============================================================================
73130
## Validation of session, robot, and user labels.
74131
##==============================================================================
@@ -83,10 +140,8 @@ $(SIGNATURES)
83140
Returns true if the label is valid for node.
84141
"""
85142
function isValidLabel(id::Union{Symbol, String})
86-
if typeof(id) == Symbol
87-
id = String(id)
88-
end
89-
return !in(uppercase(id), _invalidIds) && !isnothing(match(_validLabelRegex, id))
143+
_id = string(id)
144+
return occursin(_validLabelRegex, _id) && !in(uppercase(_id), _invalidIds)
90145
end
91146

92147
"""

src/DataBlobs/services/BlobEntry.jl

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ Get data entry
6565
6666
Also see: [`addBlobentry!`](@ref), [`getBlob`](@ref), [`listBlobentries`](@ref)
6767
"""
68-
function getBlobentry(var::AbstractDFGVariable, key::Symbol)
68+
function getBlobentry(var::AbstractGraphVariable, key::Symbol)
6969
if !hasBlobentry(var, key)
7070
throw(LabelNotFoundError("Blobentry", key, collect(keys(var.dataDict))))
7171
end
@@ -85,7 +85,7 @@ Finds and returns the first blob entry that matches the filter.
8585
8686
Also see: [`getBlobentry`](@ref)
8787
"""
88-
function getfirstBlobentry(var::AbstractDFGVariable, blobId::UUID)
88+
function getfirstBlobentry(var::AbstractGraphVariable, blobId::UUID)
8989
for (k, v) in var.dataDict
9090
if blobId == v.blobId
9191
return v
@@ -98,7 +98,7 @@ function getfirstBlobentry(dfg::AbstractDFG, label::Symbol, blobId::UUID)
9898
return getfirstBlobentry(getVariable(dfg, label), blobId)
9999
end
100100

101-
function getfirstBlobentry(var::AbstractDFGVariable, key::Regex)
101+
function getfirstBlobentry(var::AbstractGraphVariable, key::Regex)
102102
for (k, v) in var.dataDict
103103
if occursin(key, string(v.label))
104104
return v
@@ -152,7 +152,7 @@ Should be extended if DFG variable is not returned by reference.
152152
153153
Also see: [`getBlobentry`](@ref), [`addBlob!`](@ref), [`mergeBlobentries!`](@ref)
154154
"""
155-
function addBlobentry!(var::AbstractDFGVariable, entry::Blobentry)
155+
function addBlobentry!(var::AbstractGraphVariable, entry::Blobentry)
156156
# see https://github.com/JuliaRobotics/DistributedFactorGraphs.jl/issues/985
157157
# blobId::Union{UUID,Nothing} = (isnothing(entry.blobId) ? entry.id : entry.blobId),
158158
# blobSize::Int = (hasfield(Blobentry, :size) ? entry.size : -1)
@@ -182,7 +182,7 @@ Update a Blobentry in the factor graph.
182182
If the Blobentry does not exist, it will be added.
183183
Notes:
184184
"""
185-
function mergeBlobentry!(var::AbstractDFGVariable, bde::Blobentry)
185+
function mergeBlobentry!(var::AbstractGraphVariable, bde::Blobentry)
186186
if !haskey(var.dataDict, bde.label)
187187
addBlobentry!(var, bde)
188188
else
@@ -203,7 +203,7 @@ Note this doesn't remove it from any data stores.
203203
Notes:
204204
- users responsibility to delete data in db before deleting entry
205205
"""
206-
function deleteBlobentry!(var::AbstractDFGVariable, key::Symbol)
206+
function deleteBlobentry!(var::AbstractGraphVariable, key::Symbol)
207207
pop!(var.dataDict, key)
208208
return 1
209209
end
@@ -226,7 +226,7 @@ function deleteBlobentry!(dfg::AbstractDFG, label::Symbol, key::Symbol)
226226
return deleteBlobentry!(getVariable(dfg, label), key)
227227
end
228228

229-
function deleteBlobentry!(var::AbstractDFGVariable, entry::Blobentry)
229+
function deleteBlobentry!(var::AbstractGraphVariable, entry::Blobentry)
230230
#users responsibility to delete data in db before deleting entry
231231
return deleteBlobentry!(var, entry.label)
232232
end
@@ -240,7 +240,8 @@ end
240240
241241
Does a blob entry exist with `blobLabel`.
242242
"""
243-
hasBlobentry(var::AbstractDFGVariable, blobLabel::Symbol) = haskey(var.dataDict, blobLabel)
243+
hasBlobentry(var::AbstractGraphVariable, blobLabel::Symbol) =
244+
haskey(var.dataDict, blobLabel)
244245

245246
function hasBlobentry(var::VariableDFG, label::Symbol)
246247
return label in getproperty.(var.blobEntries, :label)
@@ -251,7 +252,7 @@ end
251252
252253
Get blob entries, Vector{Blobentry}
253254
"""
254-
function getBlobentries(var::AbstractDFGVariable)
255+
function getBlobentries(var::AbstractGraphVariable)
255256
#or should we return the iterator, Base.ValueIterator{Dict{Symbol,Blobentry}}?
256257
return collect(values(var.dataDict))
257258
end
@@ -311,7 +312,7 @@ end
311312
$(SIGNATURES)
312313
List the blob entries associated with a particular variable.
313314
"""
314-
function listBlobentries(var::AbstractDFGVariable)
315+
function listBlobentries(var::AbstractGraphVariable)
315316
return collect(keys(var.dataDict))
316317
end
317318

src/DataBlobs/services/BlobStores.jl

Lines changed: 9 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ Get the data blob for the specified blobstore or dfg.
77
88
Related
99
[`getBlobentry`](@ref)
10+
Implement
11+
`getBlob(store::AbstractBlobstore, blobId::UUID)`
1012
1113
$(METHODLIST)
1214
"""
@@ -17,67 +19,31 @@ Adds a blob to the blob store or dfg with the blobId.
1719
1820
Related
1921
[`addBlobentry!`](@ref)
20-
22+
Implement
23+
`addBlob!(store::AbstractBlobstore, blobId::UUID, data)`
2124
$(METHODLIST)
2225
"""
2326
function addBlob! end
2427

25-
"""
26-
Update a blob to the blob store or dfg with the given entry.
27-
Related
28-
[`mergeBlobentry!`](@ref)
29-
30-
$(METHODLIST)
31-
32-
DevNotes
33-
- TODO TBD update verb on data since data blobs and entries are restricted to immutable only.
34-
"""
35-
function updateBlob! end
36-
3728
"""
3829
Delete a blob from the blob store or dfg with the given entry.
3930
4031
Related
4132
[`deleteBlobentry!`](@ref)
42-
33+
Implement
34+
`deleteBlob!(store::AbstractBlobstore, blobId::UUID)`
4335
$(METHODLIST)
4436
"""
4537
function deleteBlob! end
4638

4739
"""
4840
$(SIGNATURES)
49-
List all ids in the blob store.
41+
List all `blobId`s in the blob store.
42+
Implement
43+
`listBlobs(store::AbstractBlobstore)`
5044
"""
5145
function listBlobs end
5246

53-
##==============================================================================
54-
## AbstractBlobstore CRUD Interface
55-
##==============================================================================
56-
57-
function getBlob(store::AbstractBlobstore, ::UUID)
58-
return error("$(typeof(store)) doesn't override 'getBlob'.")
59-
end
60-
61-
function addBlob!(store::AbstractBlobstore{T}, ::UUID, ::T) where {T}
62-
return error("$(typeof(store)) doesn't override 'addBlob!'.")
63-
end
64-
65-
function updateBlob!(store::AbstractBlobstore{T}, ::UUID, ::T) where {T}
66-
return error("$(typeof(store)) doesn't override 'updateBlob!'.")
67-
end
68-
69-
function deleteBlob!(store::AbstractBlobstore, ::UUID)
70-
return error("$(typeof(store)) doesn't override 'deleteBlob!'.")
71-
end
72-
73-
function listBlobs(store::AbstractBlobstore)
74-
return error("$(typeof(store)) doesn't override 'listBlobs'.")
75-
end
76-
77-
function hasBlob(store::AbstractBlobstore, ::UUID)
78-
return error("$(typeof(store)) doesn't override 'hasBlob'.")
79-
end
80-
8147
##==============================================================================
8248
## AbstractBlobstore derived CRUD for Blob
8349
##==============================================================================

0 commit comments

Comments
 (0)