Skip to content

Commit 502344d

Browse files
committed
writeSignalTable(..) further improved + new keyword arguments for getSignalNames(..)
1 parent 4f3197d commit 502344d

File tree

4 files changed

+99
-79
lines changed

4 files changed

+99
-79
lines changed

docs/src/index.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -190,9 +190,12 @@ are different to the Python 2.x version.
190190

191191
### Version 0.4.1
192192

193-
- writeSignalTable(..., log=false):
194-
- Info messages about not written elements only printed if log=true.
195-
- Some issues corrected when writing signals.
193+
- getSignalNames(signalTable; getVar=true, getPar=true, getMap=true): New keyword arguments
194+
getVar, getPar, getMap to only return names of the specified signal categories.
195+
196+
- writeSignalTable(...): Some issues corrected.
197+
198+
- @error replaced by error(..).
196199

197200
### Version 0.4.0
198201

src/AbstractSignalTableInterface.jl

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -23,37 +23,44 @@ function getIndependentSignalNames(obj)
2323
if Tables.istable(obj) && Tables.columnaccess(obj)
2424
return [string(Tables.columnnames(obj)[1])]
2525
else
26-
@error "getIndependentSignalNames(obj) is not supported for typeof(obj) = " * string(typeof(obj))
26+
error("getIndependentSignalNames(obj) is not supported for typeof(obj) = " * string(typeof(obj)))
2727
end
2828
end
2929

3030

3131
"""
32-
getSignalNames(signalTable)::Vector{String}
32+
getSignalNames(signalTable; getVar=true, getPar=true, getMap=true)::Vector{String}
3333
3434
Returns a string vector of the signal names that are present in signalTable
3535
(including independent signal names).
36+
- If getVar=true, Var(..) variables are included.
37+
- If getPar=true, Par(..) variables are included.
38+
- If getMap=true, Map(..) variables are included.
3639
"""
37-
function getSignalNames(obj)
40+
function getSignalNames(obj; getVar=true, getPar=true, getMap=true)
3841
if Tables.istable(obj) && Tables.columnaccess(obj)
39-
return string.(Tables.columnnames(obj))
42+
if !getVar
43+
return String[]
44+
else
45+
return string.(Tables.columnnames(obj))
46+
end
4047
else
41-
@error "getSignalNames(obj) is not supported for typeof(obj) = " * string(typeof(obj))
48+
error("getSignalNames(obj) is not supported for typeof(obj) = " * string(typeof(obj)))
4249
end
4350
end
4451

4552

4653
"""
4754
getSignal(signalTable, name::String)
4855
49-
Returns signal `name` from `signalTable` (that is a [`Var`](@ref) or a [`Par`](@ref)).
56+
Returns signal `name` from `signalTable` (that is a [`Var`](@ref), a [`Par`](@ref) or a [`Map`](@ref)).
5057
If `name` does not exist, an error is raised.
5158
"""
5259
function getSignal(obj, name::String)
5360
if Tables.istable(obj) && Tables.columnaccess(obj)
5461
return Var(values= Tables.getcolumn(obj, Symbol(name)))
5562
else
56-
@error "getSignal(obj, \"$name\") is not supported for typeof(obj) = " * string(typeof(obj))
63+
error("getSignal(obj, \"$name\") is not supported for typeof(obj) = " * string(typeof(obj)))
5764
end
5865
end
5966

@@ -80,52 +87,52 @@ end
8087
getSignalInfo(signalTable, name::String)
8188
8289
Returns signal, but [`Var`](@ref) or [`Par`](@ref)) without :values or :value
83-
but instead with :_eltypeOrType (eltype of the values if AbstractArray, otherwise typeof the values)
90+
but instead with :_eltypeOrType (eltype of the values if AbstractArray, otherwise typeof the values)
8491
and :_size (if defined on the values)
85-
92+
8693
If `name` does not exist, an error is raised.
8794
8895
This function is useful if only the attributes of a signal are needed, but not their values
89-
(returning the attributes might be a *cheap* operation, whereas returning the values
96+
(returning the attributes might be a *cheap* operation, whereas returning the values
9097
might be an *expensive* operation).
9198
"""
9299
function getSignalInfo(signalTable, name::String)::SymbolDictType
93100
signal = getSignal(signalTable,name)
94101
signal2 = copy(signal)
95102
delete!(signal2, :values)
96103
delete!(signal2, :value)
97-
_eltypeOrType = nothing
104+
_eltypeOrType = nothing
98105
_size = nothing
99106
type_available = false
100-
size_available = false
107+
size_available = false
101108
if isVar(signal)
102109
if haskey(signal, :values)
103110
type_available = true
104111
try
105112
sig = signal[:values]
106113
_eltypeOrType = eltypeOrType(sig)
107114
_size = size(sig)
108-
size_available = true
115+
size_available = true
109116
catch
110117
size_available = false
111118
end
112119
end
113120
else
114121
if haskey(signal, :value)
115-
type_available = true
122+
type_available = true
116123
try
117124
sig = signal[:value]
118-
_eltypeOrType = eltypeOrType(sig)
125+
_eltypeOrType = eltypeOrType(sig)
119126
_size = size(sig)
120-
size_available = true
127+
size_available = true
121128
catch
122129
size_available = false
123130
end
124131
end
125132
end
126133
if type_available
127134
signal2[:_eltypeOrType] = _eltypeOrType
128-
end
135+
end
129136
if size_available
130137
signal2[:_size] = _size
131138
end
@@ -136,7 +143,7 @@ end
136143
"""
137144
getIndependentSignalsSize(signalTable)::Dims
138145
139-
Returns the lengths of the independent signals as Dims.
146+
Returns the lengths of the independent signals as Dims.
140147
E.g. for one independent signal of length 5 return (5,),
141148
or for two independent signals of length 5 and 7 return (5,7).
142149
"""

src/SignalTable.jl

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
66
Returns a new SignalTable dictionary.
77
8-
Arguments `args...` are dictionary pairs where `values` must be [`Var`](@ref)(...) and/or
8+
Arguments `args...` are dictionary pairs where `values` must be [`Var`](@ref)(...) and/or
99
[`Par`](@ref)(...) and/or [`Map`](@ref)(...). Example:
1010
1111
The *first* argument must define the *independent* signal, that is, `Var(values=..., independent=true), ...`
@@ -48,15 +48,15 @@ This results in the following output:
4848
name unit size eltypeOrType kind attributes
4949
─────────────────────────────────────────────────────────────────────────────────────────────────────────
5050
time "s" [6] Float64 Var independent=true
51-
load.r "m" [6,3] Float64 Var
51+
load.r "m" [6,3] Float64 Var
5252
motor.angle "rad" [6] Float64 Var state=true, der="motor.w"
53-
motor.w "rad/s" [6] Float64 Var
53+
motor.w "rad/s" [6] Float64 Var
5454
motor.w_ref ["rad", "1/s"] [6,2] Float64 Var info="Reference angle and speed"
5555
wm "rad/s" [6] Float64 Var alias="motor.w"
5656
ref.clock [6] Union{Missing,Bool} Var variability="clock"
5757
motor.w_c [6] Union{Missing,Float64} Var variability="clocked", clock="ref.clock"
58-
motor.inertia "kg*m/s^2" Float32 Par
59-
motor.data String Par
58+
motor.inertia "kg*m/s^2" Float32 Par
59+
motor.data String Par
6060
attributes Map experiment=Map(stoptime=0.5, interval=0.01)
6161
```
6262
@@ -98,7 +98,7 @@ struct SignalTable <: AbstractDict{String,Any}
9898
sig_values = sig[:values]
9999
if !(typeof(sig_values) <: AbstractArray)
100100
error("SignalTable(\"$key\" => signal, ...): typeof(signal[:values]) = $(typeof(sig_values)) but must be an `<: AbstractArray`!")
101-
end
101+
end
102102
if get(sig, :independent, false)
103103
k += 1
104104
ndims_sig = ndims(sig_values)
@@ -113,11 +113,11 @@ struct SignalTable <: AbstractDict{String,Any}
113113
error("SignalTable(\"$key\" => signal, ...): size(signal[:values],$i) = $(size(sig_values,i)) but must be $val (= length of independent signal)!")
114114
end
115115
end
116-
end
116+
end
117117
else
118118
# Needs not have :values, e.g. alias
119119
# error("SignalTable(\"$key\" => signal, ...) is a Var(..) and has no key :values which is required!")
120-
end
120+
end
121121
if haskey(sig, :alias)
122122
aliasName = sig[:alias]
123123
if haskey(sig,:values)
@@ -126,7 +126,7 @@ struct SignalTable <: AbstractDict{String,Any}
126126
error("SignalTable(\"$key\" => Var(alias=\"$aliasName\"...): referenced signal does not exist.")
127127
end
128128
sigAlias = dict[aliasName]
129-
sig = merge(sigAlias,sig)
129+
sig = merge(sigAlias,sig)
130130
end
131131
elseif isPar(sig)
132132
if haskey(sig, :alias)
@@ -190,13 +190,26 @@ end
190190
isSignalTable( sigTable::SignalTable) = true
191191
getIndependentSignalNames(sigTable::SignalTable) = sigTable.independendentSignalNames
192192
getIndependentSignalsSize(sigTable::SignalTable) = sigTable.independentSignalsSize
193-
getSignalNames(sigTable::SignalTable) = setdiff(String.(keys(sigTable)), ["_class"])
194193
getSignal( sigTable::SignalTable, name::String) = sigTable[name]
195194
hasSignal( sigTable::SignalTable, name::String) = haskey(sigTable, name)
195+
function getSignalNames(sigTable::SignalTable; getVar=true, getPar=true, getMap=true)
196+
if getVar && getPar && getMap
197+
sigNames = setdiff(String.(keys(sigTable)), ["_class"])
198+
else
199+
sigNames = String[]
200+
for (key,value) in sigTable.dict
201+
if getVar && isVar(value) ||
202+
getPar && isPar(value) ||
203+
getMap && isMap(value)
204+
push!(sigNames, key)
205+
end
206+
end
207+
end
208+
return sigNames
209+
end
196210

197-
198-
function getDefaultHeading(sigTable::SignalTable)::String
199-
attr = get(sigTable, "attributes", "")
211+
function getDefaultHeading(sigTable::SignalTable)::String
212+
attr = get(sigTable, "attributes", "")
200213
if attr == ""
201214
return ""
202215
else
@@ -207,7 +220,7 @@ end
207220

208221
"""
209222
toSignalTable(signalTable)::SignalTable
210-
223+
211224
Returns a signalTable as instance of [`SignalTable`](@ref).
212225
"""
213226
function toSignalTable(sigTable)::SignalTable
@@ -217,7 +230,7 @@ function toSignalTable(sigTable)::SignalTable
217230
sigTable2 = SignalTable()
218231
for name in getSignalNames(sigTable)
219232
sigTable2[name] = getSignal(sigTable,name)
220-
end
233+
end
221234
return sigTable2
222235
end
223236

src/SignalTableFunctions.jl

Lines changed: 40 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ function showInfo(io::IO, signalTable;
189189
kind2 = String[]
190190
attr2 = String[]
191191

192-
sigNames = getSignalNames(signalTable)
192+
sigNames = getSignalNames(signalTable, getVar=showVar, getPar=showPar, getMap=showMap)
193193
if sorted
194194
sigNames = sort(sigNames)
195195
end
@@ -672,7 +672,7 @@ getHeading(signalTable, heading::AbstractString) = heading != "" ? heading : get
672672

673673
import JSON
674674

675-
const TypesWithoutEncoding = Set(["Float64", "Int64", "Bool", "String", "Symbol"])
675+
const TypesWithoutEncoding = Set([Float64, Int64, Bool, String, Symbol])
676676

677677
appendNames(name1, name2) = name1 == "" ? name2 : name1 * "." * string(name2)
678678

@@ -710,6 +710,11 @@ function encodeSignalTable(signalTable; signalNames=nothing, log=false)
710710
end
711711
end
712712

713+
arrayElementBaseType(::Type{T}) where {T} = T
714+
arrayElementBaseType(::Type{Array{T,N}}) where {T,N} = arrayElementBaseType(T)
715+
arrayElementBaseType(::Type{Union{Missing,T}}) where {T} = T
716+
arrayElementBaseType(A::Type{<:AbstractArray}) = arrayElementBaseType(eltype(A))
717+
713718

714719
"""
715720
jsigDict = encodeSignalTableElement(path, signalTableElement; log=false)
@@ -727,7 +732,7 @@ function encodeSignalTableElement(path, element; log=false)
727732
end
728733
available = false
729734
for (key,val) in element
730-
if key != ":_class"
735+
if key != :_class
731736
encodedSignal = encodeSignalTableElement(appendNames(path,key),val, log=log)
732737
if !isnothing(encodedSignal)
733738
available = true
@@ -741,61 +746,53 @@ function encodeSignalTableElement(path, element; log=false)
741746
return nothing
742747
end
743748

744-
# elseif typeof(element) <: AbstractArray && (elementBaseType(eltype(element)) <: Number || elementBaseType(eltype(element)) <: String)
745-
elseif typeof(element) <: AbstractArray
746-
if ndims(element) == 1
747-
eltypeElement = eltype(element)
748-
if string(eltypeElement) in TypesWithoutEncoding || eltypeElement <: AbstractArray && ndims(eltypeElement) == 1
749+
else
750+
elementType = typeof(element)
751+
if elementType <: AbstractArray && (arrayElementBaseType(elementType) <: Number || arrayElementBaseType(elementType) <: String)
752+
if ndims(element) == 1 && arrayElementBaseType(elementType) in TypesWithoutEncoding
749753
return element
750754
else
751-
if log
752-
@info "$path::$(typeof(element)) is ignored, because mapping to JSON not known"
755+
elunit = unitAsParseableString(element)
756+
if elunit == ""
757+
jdict = OrderedDict{String,Any}("_class" => "Array",
758+
"eltype" => replace(string(eltype(element)), " " => ""),
759+
"size" => Int[i for i in size(element)],
760+
"layout" => "column-major",
761+
"values" => reshape(element, length(element)))
762+
else
763+
element = ustrip.(element)
764+
jdict = OrderedDict{String,Any}("_class" => "Array",
765+
"unit" => elunit,
766+
"eltype" => replace(string(eltype(element)), " " => ""),
767+
"size" => Int[i for i in size(element)],
768+
"layout" => "column-major",
769+
"values" => reshape(element, length(element)))
753770
end
754-
return nothing
771+
return jdict
755772
end
756-
else
773+
774+
elseif elementType in TypesWithoutEncoding
775+
return element
776+
777+
elseif elementType <: Number
757778
elunit = unitAsParseableString(element)
758779
if elunit == ""
759-
jdict = OrderedDict{String,Any}("_class" => "Array",
760-
"eltype" => string(eltype(element)),
761-
"size" => Int[i for i in size(element)],
762-
"layout" => "column-major",
763-
"values" => reshape(element, length(element)))
780+
jdict = OrderedDict{String,Any}("_class" => "Number",
781+
"type" => replace(string(typeof(element)), " " => ""),
782+
"value" => element)
764783
else
765784
element = ustrip.(element)
766-
jdict = OrderedDict{String,Any}("_class" => "Array",
785+
jdict = OrderedDict{String,Any}("_class" => "Number",
767786
"unit" => elunit,
768-
"eltype" => string(eltype(element)),
769-
"size" => Int[i for i in size(element)],
770-
"layout" => "column-major",
771-
"values" => reshape(element, length(element)))
787+
"type" => replace(string(typeof(element)), " " => ""),
788+
"value" => element)
772789
end
773790
return jdict
774-
end
775-
776-
elseif string(typeof(element)) in TypesWithoutEncoding
777-
return element
778791

779-
elseif typeof(element) <: Number
780-
elunit = unitAsParseableString(element)
781-
if elunit == ""
782-
jdict = OrderedDict{String,Any}("_class" => "Number",
783-
"type" => typeof(element),
784-
"value" => element)
785792
else
786-
element = ustrip.(element)
787-
jdict = OrderedDict{String,Any}("_class" => "Number",
788-
"unit" => elunit,
789-
"type" => typeof(element),
790-
"value" => element)
791-
end
792-
return jdict
793-
794-
else
795-
if log
796793
@info "$path::$(typeof(element)) is ignored, because mapping to JSON not known"
794+
return nothing
797795
end
798-
return nothing
799796
end
800797
end
801798

0 commit comments

Comments
 (0)