Skip to content

Commit 48e33cd

Browse files
committed
add closest time and variable near
1 parent 95aecf5 commit 48e33cd

File tree

1 file changed

+83
-0
lines changed

1 file changed

+83
-0
lines changed

src/Common.jl

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ export getFactorType, getfnctype
88
export lsTypes, lsfTypes
99
export lsWho, lsfWho
1010
export *
11+
export findClosestTimestamp, findVariableNearTimestamp
1112

1213
*(a::Symbol, b::AbstractString)::Symbol = Symbol(string(a,b))
1314

@@ -320,3 +321,85 @@ function lsfWho(dfg::AbstractDFG, type::Symbol)::Vector{Symbol}
320321
end
321322
return labels
322323
end
324+
325+
326+
"""
327+
$SIGNATURES
328+
329+
Find and return the closest timestamp from two sets of Tuples. Also return the minimum delta-time (`::Millisecond`) and how many elements match from the two sets are separated by the minimum delta-time.
330+
"""
331+
function findClosestTimestamp(setA::Vector{Tuple{DateTime,T}},
332+
setB::Vector{Tuple{DateTime,S}}) where {S,T}
333+
#
334+
# build matrix of delta times, ranges on rows x vars on columns
335+
DT = Array{Millisecond, 2}(undef, length(setA), length(setB))
336+
for i in 1:length(setA), j in 1:length(setB)
337+
DT[i,j] = setB[j][1] - setA[i][1]
338+
end
339+
340+
DT .= abs.(DT)
341+
342+
# absolute time differences
343+
# DTi = (x->x.value).(DT) .|> abs
344+
345+
# find the smallest element
346+
mdt = minimum(DT)
347+
corrs = findall(x->x==mdt, DT)
348+
349+
# return the closest timestamp, deltaT, number of correspondences
350+
return corrs[1].I, mdt, length(corrs)
351+
end
352+
353+
"""
354+
$SIGNATURES
355+
356+
Find and return nearest variable labels per delta time. Function will filter on `regexFilter`, `tags`, and `solvable`.
357+
358+
DevNotes:
359+
- TODO `number` should allow returning more than one for k-nearest matches.
360+
- Future versions likely will require some optimization around the internal `getVariable` call.
361+
- Perhaps a dedicated/efficient `getVariableTimestamp` for all DFG flavors.
362+
363+
Related
364+
365+
ls, getVariableIds, findClosestTimestamp
366+
"""
367+
function findVariableNearTimestamp(dfg::AbstractDFG,
368+
timest::DateTime,
369+
regexFilter::Union{Nothing, Regex}=nothing;
370+
tags::Vector{Symbol}=Symbol[],
371+
solvable::Int=0,
372+
warnDuplicate::Bool=true,
373+
number::Int=1 )::Vector{Tuple{Vector{Symbol}, Millisecond}}
374+
#
375+
# get the variable labels based on filters
376+
# syms = getVariableIds(dfg, regexFilter, tags=tags, solvable=solvable)
377+
syms = getVariableIds(dfg, regexFilter, tags=tags, solvable=solvable)
378+
# compile timestamps with label
379+
# vars = map( x->getVariable(dfg, x), syms )
380+
timeset = map(x->(DFG.timestamp(getVariable(dfg,x)), x), syms)
381+
mask = BitArray{1}(undef, length(syms))
382+
fill!(mask, true)
383+
384+
RET = Vector{Tuple{Vector{Symbol},Millisecond}}()
385+
SYMS = Symbol[]
386+
CORRS = 1
387+
NUMBER = number
388+
while 0 < CORRS + NUMBER
389+
# get closest
390+
link, mdt, corrs = findClosestTimestamp([(timest,0)], timeset[mask])
391+
push!(SYMS, syms[link[2]])
392+
mask[link[2]] = false
393+
CORRS = corrs-1
394+
# last match, done with this delta time
395+
if corrs == 1
396+
NUMBER -= 1
397+
push!(RET, (deepcopy(SYMS),mdt))
398+
SYMS = Symbol[]
399+
end
400+
end
401+
# warn if duplicates found
402+
# warnDuplicate && 1 < corrs ? @warn("getVariableNearTimestamp found more than one variable at $timestamp") : nothing
403+
404+
return RET
405+
end

0 commit comments

Comments
 (0)