diff --git a/src/FMI.jl b/src/FMI.jl index 5c20ef2f..b2c676ae 100644 --- a/src/FMI.jl +++ b/src/FMI.jl @@ -181,16 +181,17 @@ function __init__() import .JLD2 include("extensions/JLD2.jl") end - @require DataFrames="a93c6f00-e57d-5684-b7b6-d8193f3e46c0" begin - import .DataFrames - @require CSV="336ed68f-0bac-5ca0-87d4-7b16caf5d00b" begin - import .CSV - include("extensions/CSV.jl") - end + @require CSV="336ed68f-0bac-5ca0-87d4-7b16caf5d00b" begin + import .CSV + include("extensions/CSV.jl") end @require MAT="23992714-dd62-5051-b70f-ba57cb901cac" begin import .MAT - include("extensions/MAT.jl") + include("extensions/MAT.jl") + end + @require Tables="bd369af6-aec1-5ad0-b16a-f7cc5008161c" begin + import .Tables + include("extensions/Tables.jl") end end diff --git a/src/extensions/CSV.jl b/src/extensions/CSV.jl index cb350005..dd5bc5fb 100644 --- a/src/extensions/CSV.jl +++ b/src/extensions/CSV.jl @@ -6,14 +6,14 @@ using FMIImport: FMUSolution """ -ToDo: DocString. + fmiSaveSolutionCSV(solution::FMUSolution, filepath::AbstractString) Saves a FMUSolution to a csv file. + +# Arguments +- `solution::FMUSolution`: The simulation results that should be saved +- `filepath::AbstractString`: The path specifing where to save the results, also indicating the file format. Supports *.mat, *.csv, *.JLD2 """ -function fmiSaveSolutionCSV(solution::FMUSolution, filepath::AbstractString) - df = DataFrames.DataFrame(time = solution.values.t) - for i in 1:length(solution.values.saveval[1]) - df[!, Symbol(fmi2ValueReferenceToString(solution.component.fmu, solution.valueReferences[i]))] = [val[i] for val in solution.values.saveval] - end - CSV.write(filepath, df) +function fmiSaveSolutionCSV(solution::FMUSolution, filepath::AbstractString) + CSV.write(filepath, solution) end diff --git a/src/extensions/JLD2.jl b/src/extensions/JLD2.jl index 6a766b96..3d67be0c 100644 --- a/src/extensions/JLD2.jl +++ b/src/extensions/JLD2.jl @@ -21,4 +21,4 @@ Loads a FMUSolution. Returns a previously saved `FMUSolution`. """ function fmiLoadSolutionJLD2(filepath::AbstractString; keyword="solution") return JLD2.load(filepath, keyword) -end \ No newline at end of file +end diff --git a/src/extensions/MAT.jl b/src/extensions/MAT.jl index 69677a39..f029a41f 100644 --- a/src/extensions/MAT.jl +++ b/src/extensions/MAT.jl @@ -20,6 +20,6 @@ function fmiSaveSolutionMAT(solution::FMUSolution, filepath::AbstractString) MAT.write(file, replace(fmi2ValueReferenceToString(solution.component.fmu, solution.valueReferences[i-1])[1], "." => "_"), v[:,i]) # df[!, Symbol(fmi2ValueReferenceToString(solution.component.fmu, solution.valueReferences[i]))] = [val[i] for val in solution.values.saveval] end - + MAT.close(file) -end \ No newline at end of file +end diff --git a/src/extensions/Tables.jl b/src/extensions/Tables.jl new file mode 100644 index 00000000..e9a694c5 --- /dev/null +++ b/src/extensions/Tables.jl @@ -0,0 +1,55 @@ +# +# Copyright (c) 2023 Andreas Heuermann +# Licensed under the MIT license. See LICENSE file in the project root for details. +# + +using FMIImport: FMUSolution + +# Declare that FMUSolution is a table +Tables.istable(::Type{<:FMUSolution}) = true + +# TODO: Define [optional] schema + +# Column interface +Tables.columnaccess(table) = true + +function Tables.columns(solution::FMUSolution) + return solution +end + +""" +Retrieve a column by index. +""" +function Tables.getcolumn(solution::FMUSolution, i::Int)::Vector{Float64} + if i == 1 # Time + return solution.values.t + end + # Variables + return [val[i-1] for val in solution.values.saveval] +end + +""" +Retrieve a column by name. +""" +function Tables.getcolumn(solution::FMUSolution, nm::Symbol) + if nm == :time # Time + return solution.values.t + end + # Variables + vr = first(fmi2StringToValueReference(solution.component.fmu, string(nm))) + idx = findfirst(idx -> idx == vr, solution.valueReferences) + return [val[idx] for val in solution.values.saveval] +end + +""" +Return column names for a table as an indexable collection. +""" +function Tables.columnnames(solution::FMUSolution) + names = Symbol[] + push!(names, Symbol("time")) + for i in 1:length(solution.values.saveval[1]) + var = fmi2ValueReferenceToString(solution.component.fmu, solution.valueReferences[i]) + append!(names, Symbol.(var)) + end + return unique(names) +end diff --git a/test/Project.toml b/test/Project.toml index 67a7f363..ce43a2a8 100644 --- a/test/Project.toml +++ b/test/Project.toml @@ -10,11 +10,14 @@ Logging = "56ddb016-857b-54e1-b83d-db4d58db5568" MAT = "23992714-dd62-5051-b70f-ba57cb901cac" Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" +Tables = "bd369af6-aec1-5ad0-b16a-f7cc5008161c" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" Zygote = "e88e6eb3-aa80-5325-afca-941959d7151f" [compat] julia = "1.6" +Tables = "1" +JLD2 = "< 0.4.37, > 0.4.38" [extras] CPUSummary = "2a0fbf3d-bb9c-48f3-b0a9-814d99fd7ab9"