Skip to content

Commit f031852

Browse files
committed
Functions added to encode and write a SignalTable instance to a file or a string in JSON format
1 parent 88e1ea8 commit f031852

File tree

8 files changed

+147
-40
lines changed

8 files changed

+147
-40
lines changed

Project.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,15 @@ version = "0.2.1-dev"
55

66
[deps]
77
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
8+
JSON = "682c06a0-de6a-54ab-a142-c8b1cf79cde6"
89
OrderedCollections = "bac558e1-5e72-5ebc-8fee-abe8a469f55d"
910
Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
1011
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
1112
Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d"
1213

1314
[compat]
1415
DataFrames = "1, 0.22, 0.21, 0.20, 0.19"
16+
JSON = "0.21"
1517
OrderedCollections = "1"
1618
Pkg = "1"
1719
Unitful = "1"
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"time":{"_class":"Var","values":[0.0,0.1,0.2,0.3,0.4,0.5],"unit":"s","independent":true},"load.r":{"_class":"Var","values":[[0.0,0.09983341664682815,0.19866933079506122,0.29552020666133955,0.3894183423086505,0.479425538604203],[1.0,0.9950041652780258,0.9800665778412416,0.955336489125606,0.9210609940028851,0.8775825618903728],[0.0,0.09983341664682815,0.19866933079506122,0.29552020666133955,0.3894183423086505,0.479425538604203]],"unit":"m"},"motor.angle":{"_class":"Var","values":[0.0,0.09983341664682815,0.19866933079506122,0.29552020666133955,0.3894183423086505,0.479425538604203],"unit":"rad","state":true},"motor.w":{"_class":"Var","values":[1.0,0.9950041652780258,0.9800665778412416,0.955336489125606,0.9210609940028851,0.8775825618903728],"unit":"rad/s","integral":"motor.angle"},"motor.w_ref":{"_class":"Var","values":[[0.0,0.08985007498214534,0.1788023977155551,0.2659681859952056,0.35047650807778546,0.4314829847437827],[0.9,0.8955037487502232,0.8820599200571175,0.8598028402130454,0.8289548946025966,0.7898243057013355]],"unit":["rad","1/s"],"info":"Reference angle and speed"},"wm":{"_class":"Var","values":[1.0,0.9950041652780258,0.9800665778412416,0.955336489125606,0.9210609940028851,0.8775825618903728],"unit":"rad/s","integral":"motor.angle","alias":"motor.w"},"ref.clock":{"_class":"Var","values":[true,null,null,true,null,null],"variability":"clock"},"motor.w_c":{"_class":"Var","values":[0.6,null,null,0.8,null,null],"variability":"clocked","clock":"ref.clock"},"motor.inertia":{"_class":"Par","value":0.02,"unit":"kg*m/s^2"},"motor.data":{"_class":"Par","value":"resources/motorMap.json"},"attributes":{"_class":"Par","info":"This is a test signal table"}}
1+
{"_class":"SignalTable","time":{"_class":"Var","values":[0.0,0.1,0.2,0.3,0.4,0.5],"unit":"s","independent":true},"load.r":{"_class":"Var","values":{"_class":"Array","eltype":"Float64","size":[6,3],"values":[0.0,0.09983341664682815,0.19866933079506122,0.29552020666133955,0.3894183423086505,0.479425538604203,1.0,0.9950041652780258,0.9800665778412416,0.955336489125606,0.9210609940028851,0.8775825618903728,0.0,0.09983341664682815,0.19866933079506122,0.29552020666133955,0.3894183423086505,0.479425538604203]},"unit":"m"},"motor.angle":{"_class":"Var","values":[0.0,0.09983341664682815,0.19866933079506122,0.29552020666133955,0.3894183423086505,0.479425538604203],"unit":"rad","state":true,"der":"motor.w"},"motor.w":{"_class":"Var","values":[1.0,0.9950041652780258,0.9800665778412416,0.955336489125606,0.9210609940028851,0.8775825618903728],"unit":"rad/s"},"motor.w_ref":{"_class":"Var","values":{"_class":"Array","eltype":"Float64","size":[6,2],"values":[0.0,0.08985007498214534,0.1788023977155551,0.2659681859952056,0.35047650807778546,0.4314829847437827,0.9,0.8955037487502232,0.8820599200571175,0.8598028402130454,0.8289548946025966,0.7898243057013355]},"unit":["rad","1/s"],"info":"Reference angle and speed"},"wm":{"_class":"Var","values":[1.0,0.9950041652780258,0.9800665778412416,0.955336489125606,0.9210609940028851,0.8775825618903728],"unit":"rad/s","alias":"motor.w"},"ref.clock":{"_class":"Var","values":[true,null,null,true,null,null],"variability":"clock"},"motor.w_c":{"_class":"Var","values":[0.6,null,null,0.8,null,null],"variability":"clocked","clock":"ref.clock"},"motor.inertia":{"_class":"Par","value":{"_class":"Number","type":"Float32","value":0.02},"unit":"kg*m/s^2"},"motor.data":{"_class":"Par","value":"resources/motorMap.json"},"attributes":{"_class":"Par","info":"This is a test signal table"}}

docs/resources/examples/fileIO/VariousTypes_prettyPrint.json

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
{
2+
"_class": "SignalTable",
23
"time": {
34
"_class": "Var",
45
"values": [
@@ -14,32 +15,34 @@
1415
},
1516
"load.r": {
1617
"_class": "Var",
17-
"values": [
18-
[
18+
"values": {
19+
"_class": "Array",
20+
"eltype": "Float64",
21+
"size": [
22+
6,
23+
3
24+
],
25+
"values": [
1926
0.0,
2027
0.09983341664682815,
2128
0.19866933079506122,
2229
0.29552020666133955,
2330
0.3894183423086505,
24-
0.479425538604203
25-
],
26-
[
31+
0.479425538604203,
2732
1.0,
2833
0.9950041652780258,
2934
0.9800665778412416,
3035
0.955336489125606,
3136
0.9210609940028851,
32-
0.8775825618903728
33-
],
34-
[
37+
0.8775825618903728,
3538
0.0,
3639
0.09983341664682815,
3740
0.19866933079506122,
3841
0.29552020666133955,
3942
0.3894183423086505,
4043
0.479425538604203
4144
]
42-
],
45+
},
4346
"unit": "m"
4447
},
4548
"motor.angle": {
@@ -53,7 +56,8 @@
5356
0.479425538604203
5457
],
5558
"unit": "rad",
56-
"state": true
59+
"state": true,
60+
"der": "motor.w"
5761
},
5862
"motor.w": {
5963
"_class": "Var",
@@ -65,29 +69,32 @@
6569
0.9210609940028851,
6670
0.8775825618903728
6771
],
68-
"unit": "rad/s",
69-
"integral": "motor.angle"
72+
"unit": "rad/s"
7073
},
7174
"motor.w_ref": {
7275
"_class": "Var",
73-
"values": [
74-
[
76+
"values": {
77+
"_class": "Array",
78+
"eltype": "Float64",
79+
"size": [
80+
6,
81+
2
82+
],
83+
"values": [
7584
0.0,
7685
0.08985007498214534,
7786
0.1788023977155551,
7887
0.2659681859952056,
7988
0.35047650807778546,
80-
0.4314829847437827
81-
],
82-
[
89+
0.4314829847437827,
8390
0.9,
8491
0.8955037487502232,
8592
0.8820599200571175,
8693
0.8598028402130454,
8794
0.8289548946025966,
8895
0.7898243057013355
8996
]
90-
],
97+
},
9198
"unit": [
9299
"rad",
93100
"1/s"
@@ -105,7 +112,6 @@
105112
0.8775825618903728
106113
],
107114
"unit": "rad/s",
108-
"integral": "motor.angle",
109115
"alias": "motor.w"
110116
},
111117
"ref.clock": {
@@ -135,7 +141,11 @@
135141
},
136142
"motor.inertia": {
137143
"_class": "Par",
138-
"value": 0.02,
144+
"value": {
145+
"_class": "Number",
146+
"type": "Float32",
147+
"value": 0.02
148+
},
139149
"unit": "kg*m/s^2"
140150
},
141151
"motor.data": {

docs/src/Examples/FileIO.md

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,44 +9,32 @@ CurrentModule = SignalTables
99
## JSON - Write to File
1010

1111
```julia
12-
using SignalTables
13-
import JSON
12+
using SignalTables
1413

1514
sigTable = getSignalTableExample("VariousTypes")
16-
17-
open("VariousTypes_prettyPrint.json", "w") do io
18-
JSON.print(io, sigTable, 2)
19-
end
20-
21-
open("VariousTypes_compact.json", "w") do io
22-
JSON.print(io, sigTable)
23-
end
15+
writeSignalTable("VariousTypes_prettyPrint.json", sigTable; indent=2, log=true)
16+
writeSignalTable("VariousTypes_compact.json" , sigTable)
2417
```
2518

2619
results in the following files
2720

2821
- [VariousTypes_prettyPrint.json](../../resources/examples/fileIO/VariousTypes_prettyPrint.json).
29-
3022
- [VariousTypes_compact.json](../../resources/examples/fileIO/VariousTypes_compact.json).
3123

3224

33-
3425
## JSON - Write to String
3526

3627
```julia
3728
using SignalTables
38-
import JSON
39-
40-
sigTable = getSignalTableExample("VariousTypes")
41-
str = JSON.json(sigTable)
4229

43-
println("VariousType string = ", str)
30+
str = signalTableToJSON( getSignalTableExample("VariousTypes") )
31+
println(str)
4432
```
4533

4634
results in the following print output
4735

4836
```julia
49-
VariousType string = {"time":{"_class":"Var","values":[0.0,0.1,0.2,0.3,0.4,0.5],"unit":"s","independent":true},"load.r":{"_class":"Var","values":[[0.0,0.09983341664682815,0.19866933079506122,0.29552020666133955,0.3894183423086505,0.479425538604203],[1.0,0.9950041652780258,0.9800665778412416,0.955336489125606,0.9210609940028851,0.8775825618903728],[0.0,0.09983341664682815,0.19866933079506122,0.29552020666133955,0.3894183423086505,0.479425538604203]],"unit":"m"},"motor.angle":{"_class":"Var","values":[0.0,0.09983341664682815,0.19866933079506122,0.29552020666133955,0.3894183423086505,0.479425538604203],"unit":"rad","state":true},"motor.w":{"_class":"Var","values":[1.0,0.9950041652780258,0.9800665778412416,0.955336489125606,0.9210609940028851,0.8775825618903728],"unit":"rad/s","integral":"motor.angle"},"motor.w_ref":{"_class":"Var","values":[[0.0,0.08985007498214534,0.1788023977155551,0.2659681859952056,0.35047650807778546,0.4314829847437827],[0.9,0.8955037487502232,0.8820599200571175,0.8598028402130454,0.8289548946025966,0.7898243057013355]],"unit":["rad","1/s"],"info":"Reference angle and speed"},"wm":{"_class":"Var","values":[1.0,0.9950041652780258,0.9800665778412416,0.955336489125606,0.9210609940028851,0.8775825618903728],"unit":"rad/s","integral":"motor.angle","alias":"motor.w"},"ref.clock":{"_class":"Var","values":[true,null,null,true,null,null],"variability":"clock"},"motor.w_c":{"_class":"Var","values":[0.6,null,null,0.8,null,null],"variability":"clocked","clock":"ref.clock"},"motor.inertia":{"_class":"Par","value":0.02,"unit":"kg*m/s^2"},"motor.data":{"_class":"Par","value":"resources/motorMap.json"},"attributes":{"_class":"Par","info":"This is a test signal table"}}
37+
"{\"_class\":\"SignalTable\",\"time\":{\"_class\":\"Var\",\"values\":[0.0,0.1,0.2,0.3,0.4,0.5],\"unit\":\"s\",\"independent\":true},\"load.r\":{\"_class\":\"Var\",\"values\":{\"_class\":\"Array\",\"eltype\":\"Float64\",\"size\":[6,3],\"values\":[0.0,0.09983341664682815,0.19866933079506122,0.29552020666133955,0.3894183423086505,0.479425538604203,1.0,0.9950041652780258,0.9800665778412416,0.955336489125606,0.9210609940028851,0.8775825618903728,0.0,0.09983341664682815,0.19866933079506122,0.29552020666133955,0.3894183423086505,0.479425538604203]},\"unit\":\"m\"},\"motor.angle\":{\"_class\":\"Var\",\"values\":[0.0,0.09983341664682815,0.19866933079506122,0.29552020666133955,0.3894183423086505,0" ⋯ 533 bytes ⋯ ",\"info\":\"Reference angle and speed\"},\"wm\":{\"_class\":\"Var\",\"values\":[1.0,0.9950041652780258,0.9800665778412416,0.955336489125606,0.9210609940028851,0.8775825618903728],\"unit\":\"rad/s\",\"alias\":\"motor.w\"},\"ref.clock\":{\"_class\":\"Var\",\"values\":[true,null,null,true,null,null],\"variability\":\"clock\"},\"motor.w_c\":{\"_class\":\"Var\",\"values\":[0.6,null,null,0.8,null,null],\"variability\":\"clocked\",\"clock\":\"ref.clock\"},\"motor.inertia\":{\"_class\":\"Par\",\"value\":{\"_class\":\"Number\",\"type\":\"Float32\",\"value\":0.02},\"unit\":\"kg*m/s^2\"},\"motor.data\":{\"_class\":\"Par\",\"value\":\"resources/motorMap.json\"},\"attributes\":{\"_class\":\"Par\",\"info\":\"This is a test signal table\"}}"
5038
```
5139

5240
Such a string could be communicated to a web browser.

docs/src/Functions/OverviewOfFunctions.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ Note, *FileIO* functions (e.g. JSON, HDF5) can be directly used, see [FileIO Exa
5151
| [`getValueWithUnit`](@ref) | Returns the *value* of a [`Par`](@ref) signal from a signal table including its unit. |
5252
| [`getFlattenedSignal`](@ref) | Returns a copy of a signal where the values or the value are *flattened* and converted for use in plots or traditional tables. |
5353
| [`getDefaultHeading`](@ref) | Returns the default heading for a plot. |
54+
| [`signalTableToJSON`](@ref) | Returns a JSON string representation of a [`SignalTable`](@ref) instance |
55+
| [`writeSignalTable`](@ref) | Write a [`SignalTable`](@ref) instance in JSON format on file. |
5456

5557

5658
| Plot package functions | Description |

docs/src/Functions/SignalTables.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ The functions below operate on a *signal table* that implements the [Abstract Si
2727
| [`getValueWithUnit`](@ref) | Returns the *value* of a [`Par`](@ref) signal from a signal table including its unit. |
2828
| [`getFlattenedSignal`](@ref) | Returns a copy of a signal where the values or the value are *flattened* and converted for use in plots or traditional tables. |
2929
| [`getDefaultHeading`](@ref) | Returns the default heading for a plot. |
30+
| [`signalTableToJSON`](@ref) | Returns a JSON string representation of a [`SignalTable`](@ref) instance |
31+
| [`writeSignalTable`](@ref) | Write a [`SignalTable`](@ref) instance in JSON format on file. |
3032

3133

3234
```@docs
@@ -45,4 +47,6 @@ getValue
4547
getValueWithUnit
4648
getFlattenedSignal
4749
getDefaultHeading
50+
signalTableToJSON
51+
writeSignalTable
4852
```

src/SignalTable.jl

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,3 +218,104 @@ function getDefaultHeading(sigTable::SignalTable)::String
218218
return get(attr, :plotHeading, "")
219219
end
220220
end
221+
222+
223+
224+
225+
#
226+
# Encoding and decoding Modia signalTables as JSON.
227+
#
228+
# Based on Modia/src/JSONModel.jl developed by Hilding Elmqvist
229+
# License: MIT (expat)
230+
231+
export signalTableToJSON, writeSignalTable
232+
233+
import JSON
234+
235+
const TypesWithoutEncoding = Set(["Float64", "Int64", "Bool", "String", "Symbol"])
236+
237+
appendNames(name1, name2) = name1 == "" ? name2 : name1 * "." * string(name2)
238+
239+
"""
240+
jsigDict = encodeSignalTable(name, element)
241+
242+
Encodes a SignalTable suitable to convert to a JSON string.
243+
"""
244+
function encodeSignalTable(name, element)
245+
if typeof(element) <: SignalTable
246+
jdict = OrderedDict{String,Any}("_class" => "SignalTable")
247+
for (key,val) in element
248+
jdict[key] = encodeSignalTable(appendNames(name,key),val)
249+
end
250+
return jdict
251+
252+
elseif isVar(element)
253+
jdict = OrderedDict{String,Any}("_class" => "Var")
254+
for (key,val) in element
255+
if key != :Var
256+
jdict[string(key)] = encodeSignalTable(appendNames(name,key),val)
257+
end
258+
end
259+
return jdict
260+
261+
elseif isPar(element)
262+
jdict = OrderedDict{String,Any}("_class" => "Par")
263+
for (key,val) in element
264+
if key != :Par
265+
jdict[string(key)] = encodeSignalTable(appendNames(name,key),val)
266+
end
267+
end
268+
return jdict
269+
270+
elseif typeof(element) <: AbstractArray && (elementBaseType(eltype(element)) <: Number || elementBaseType(eltype(element)) <: String)
271+
if ndims(element) == 1 && string(elementBaseType(eltype(element))) in TypesWithoutEncoding
272+
return element
273+
end
274+
jdict = OrderedDict{String,Any}("_class" => "Array",
275+
"eltype" => string(eltype(element)),
276+
"size" => Int[i for i in size(element)],
277+
"values" => reshape(element, length(element)))
278+
return jdict
279+
280+
elseif string(typeof(element)) in TypesWithoutEncoding
281+
return element
282+
283+
elseif typeof(element) <: Number
284+
jdict = OrderedDict{String,Any}("_class" => "Number",
285+
"type" => typeof(element),
286+
"value" => element)
287+
288+
else
289+
@info "$name::$(typeof(element)) is ignored, because mapping to JSON not known"
290+
return nothing
291+
end
292+
end
293+
294+
295+
"""
296+
json = signalTableToJSON(signalTable)
297+
298+
Returns a JSON string representation of signalTable
299+
"""
300+
function signalTableToJSON(signalTable)::String
301+
jsignalTable = encodeSignalTable("", signalTable)
302+
return JSON.json(jsignalTable)
303+
end
304+
305+
306+
"""
307+
writeSignalTable(filename::String, signalTable; indent=2, log=true)
308+
309+
Write signalTable in JSON format on file `filename`.
310+
"""
311+
function writeSignalTable(filename::String, signalTable::AbstractDict; indent=nothing, log=false)::Nothing
312+
file = joinpath(pwd(), filename)
313+
if log
314+
println(" Write signalTable in JSON format on file \"$file\"")
315+
end
316+
jsignalTable = encodeSignalTable("", signalTable)
317+
open(file, "w") do io
318+
JSON.print(io, jsignalTable, indent)
319+
end
320+
return nothing
321+
end

src/SignalTables.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ export isSignalTable, independentSignalNames, signalNames, hasSignal, getSignal,
2020
export new_signal_table, getValues, getValue, getValuesWithUnit, getValueWithUnit, getFlattenedSignal, showInfo, getHeading
2121

2222
# SignalTable
23-
export SignalTable
23+
export SignalTable, signalTableToJSON, writeSignalTable
2424

2525
# Plot Package
2626
export @usingPlotPackage, usePlotPackage, usePreviousPlotPackage, currentPlotPackage

0 commit comments

Comments
 (0)