TrainRun.jl/src/output.jl

139 lines
7.2 KiB
Julia
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#!/usr/bin/env julia
# -*- coding: UTF-8 -*-
# __author__ = "Max Kannenberg"
# __copyright__ = "2020-2022"
# __license__ = "ISC"
"""
createOutput(settings, drivingCourse, pointsOfInterest)
Create output information depending on `settings`, `drivingCourse` and `pointsOfInterest`.
See also [`createOutput`](@ref).
# Arguments
- `settings::Settings`: the Settings object containing settings for output format and detail.
- `drivingCourse::Vector{Dict}`: the Vector containing dictionaries for all support points.
- `pointsOfInterest::Vector{NamedTuple}`: the Vector containing tuples for the paths' points of interest.
# Examples
```julia-repl
julia> createOutput(settings_poi, drivingCourse_longdistance, pointsOfInterest_pathWithSlope)
5×11 DataFrame
Row │ label driving_mode s v t a F_T F_R R_path R_traction R_wagons
│ String String Real Real Real Real Real Real Real Real Real
─────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
1 │ view_point_1 accelerating 850.0 28.707 54.049 0.331 1.93049e5 36602.1 0.0 9088.56 27513.6
2 │ distant_signal_1 accelerating 1000.0 30.325 59.129 0.294 1.82746e5 43604.7 4344.35 9795.13 29465.2
3 │ main_signal_1 accelerating 2000.0 37.356 88.468 0.185 1.48352e5 60899.4 8688.69 13259.1 38951.5
4 │ main_signal_3 braking 9000.0 27.386 258.578 -0.375 0.0 34522.1 0.0 8537.05 25985.0
5 │ clearing_point_1 braking 9203.37 24.443 266.426 -0.375 0.0 30176.2 0.0 7389.44 22786.8
```
"""
function createOutput(settings::Settings, drivingCourse::Vector{Dict}, pointsOfInterest::Vector{NamedTuple})
if settings.outputDetail == :running_time
output::Vector{Dict} = [Dict(:t => drivingCourse[end][:t])]
elseif settings.outputDetail == :points_of_interest
# get only the driving course's support points with POI labels
# if there is no point with POI label return the information of departure and arrival (first and last points)
output = Dict[]
if isempty(pointsOfInterest)
push!(output, drivingCourse[1])
push!(output, drivingCourse[end])
else
supportPoint = 1
for POI in 1:length(pointsOfInterest)
while supportPoint <= length(drivingCourse)
if pointsOfInterest[POI][:s] == drivingCourse[supportPoint][:s]
push!(output, drivingCourse[supportPoint])
break
end
supportPoint += 1
end
end
end
elseif settings.outputDetail == :data_points
# get the driving course's support points where a new behavior section starts and the driving mode changes
output = Dict[]
# the first support point is the first data point
push!(output, drivingCourse[1])
for supportPoint in 2:length(drivingCourse)
if drivingCourse[supportPoint-1][:behavior] != drivingCourse[supportPoint][:behavior]
push!(output, drivingCourse[supportPoint])
end
end
elseif settings.outputDetail == :driving_course
output = drivingCourse
end
if settings.outputFormat == :dataframe
return createDataFrame(output, settings.outputDetail, settings.approxLevel)
elseif settings.outputFormat == :vector
return output
end
end
"""
createDataFrame(output_vector, outputDetail, approxLevel)
Create a DataFrame from `output_vector` with `outputDetail` and `approxLevel`.
See also [`createOutput`](@ref).
# Arguments
- `output_vector::Vector{Dict}`: the Vector containing all data to be outputted.
- `outputDetail::Symbol`: the detail level the DataFrame is created for.
- `approxLevel::Int`: the number of digits for rounding each Number in the DataFrame.
# Examples
```julia-repl
julia> createDataFrame(vector_pointsOfInterest, detail_data_points, approxLevel_default)
5×11 DataFrame
Row │ label driving_mode s v t a F_T F_R R_path R_traction R_wagons
│ String String Real Real Real Real Real Real Real Real Real
─────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
1 │ view_point_1 accelerating 850.0 28.707 54.049 0.331 1.93049e5 36602.1 0.0 9088.56 27513.6
2 │ distant_signal_1 accelerating 1000.0 30.325 59.129 0.294 1.82746e5 43604.7 4344.35 9795.13 29465.2
3 │ main_signal_1 accelerating 2000.0 37.356 88.468 0.185 1.48352e5 60899.4 8688.69 13259.1 38951.5
4 │ main_signal_3 braking 9000.0 27.386 258.578 -0.375 0.0 34522.1 0.0 8537.05 25985.0
5 │ clearing_point_1 braking 9203.37 24.443 266.426 -0.375 0.0 30176.2 0.0 7389.44 22786.8
```
"""
function createDataFrame(output_vector::Vector{Dict}, outputDetail::Symbol, approxLevel::Int)
if outputDetail == :running_time
# create a DataFrame with running time information
dataFrame = DataFrame(t=[round(output_vector[end][:t], digits=approxLevel)])
else # :points_of_interest, :data_points or :driving_course
columnSymbols = [:label, :behavior, :s, :v, :t, :a, :F_T, :F_R, :R_path, :R_traction, :R_wagons]
allColumns = []
for column in 1:length(columnSymbols)
if typeof(output_vector[1][columnSymbols[column]]) == String
currentStringColumn::Vector{String} = []
for point in output_vector
push!(currentStringColumn, point[columnSymbols[column]])
end
push!(allColumns, currentStringColumn)
elseif typeof(output_vector[1][columnSymbols[column]]) <: Real
currentRealColumn::Vector{Real} = []
for point in output_vector
push!(currentRealColumn, point[columnSymbols[column]])
end
currentRealColumn = round.(currentRealColumn, digits=approxLevel)
push!(allColumns, currentRealColumn)
end
end # for
# combine the columns in a data frame
dataFrame = DataFrame(label=allColumns[1], driving_mode=allColumns[2], s=allColumns[3], v=allColumns[4], t=allColumns[5], a=allColumns[6], F_T=allColumns[7], F_R=allColumns[8], R_path=allColumns[9], R_traction=allColumns[10], R_wagons=allColumns[11])
end
return dataFrame
end #createDataFrame