Refactor output detail and format and adapt examples
parent
8a97de3fdf
commit
99c873a4e7
|
@ -1,6 +1,7 @@
|
|||
#!/usr/bin/env julia
|
||||
|
||||
using TrainRuns
|
||||
using CSV
|
||||
|
||||
paths=[]
|
||||
push!(paths, Path("test/data/paths/const.yaml"))
|
||||
|
@ -8,28 +9,16 @@ push!(paths, Path("test/data/paths/slope.yaml"))
|
|||
push!(paths, Path("test/data/paths/speed.yaml"))
|
||||
push!(paths, Path("test/data/paths/realworld.yaml"))
|
||||
|
||||
settings=[]
|
||||
push!(settings, Settings("test/data/settings/driving_course.yaml"))
|
||||
|
||||
trains=[]
|
||||
push!(trains, Train("test/data/trains/freight.yaml"))
|
||||
push!(trains, Train("test/data/trains/local.yaml"))
|
||||
push!(trains, Train("test/data/trains/longdistance.yaml"))
|
||||
|
||||
driving_courses=[]
|
||||
for path in paths
|
||||
# println(" - - - - - - - - -")
|
||||
# println("path: ", path[:name])
|
||||
for train in trains
|
||||
# println("train: ", train[:name])
|
||||
for settings in settings
|
||||
push!(driving_courses, trainrun(train, path, settings))
|
||||
#driving_course = trainrun(train, path, settings)
|
||||
settings = Settings("test/data/settings/driving_course.yaml")
|
||||
|
||||
# old: if haskey(settings, :outputFormat) && settings[:outputFormat] == "CSV"
|
||||
# old: exportToCsv(resultsDict, settings)
|
||||
# old: sleep(2)
|
||||
# old: end
|
||||
end
|
||||
for p in 1:length(paths)
|
||||
for t in 1:length(trains)
|
||||
driving_course = trainrun(trains[t], paths[p], settings)
|
||||
CSV.write("docs/examples/drivingCourse_path"*string(p)*"_train"*string(t)*".csv", driving_course, header=false)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -5,6 +5,7 @@ using TrainRuns
|
|||
train = Train("test/data/trains/freight.yaml")
|
||||
path = Path("test/data/paths/const.yaml")
|
||||
|
||||
runtime = trainrun(train, path)
|
||||
runtime_dataFrame = trainrun(train, path)
|
||||
runtime = runtime_dataFrame[!, 1][2]
|
||||
|
||||
println("The train needs $runtime seconds for the running path.")
|
||||
|
|
|
@ -13,13 +13,13 @@ using UUIDs, Dates, Statistics
|
|||
## loading external packages
|
||||
using YAML, JSONSchema, DataFrames
|
||||
|
||||
export
|
||||
export
|
||||
## Interface
|
||||
trainrun, Train, Path, Settings
|
||||
|
||||
## global variables
|
||||
global g = 9.80665 # acceleration due to gravity (in m/s^2)
|
||||
global μ = 0.2 # friction as constant, todo: implement as function
|
||||
global μ = 0.2 # friction as constant, TODO: implement as function
|
||||
global Δv_air = 15.0/3.6 # coefficient for velocitiy difference between train and outdoor air (in m/s)
|
||||
|
||||
## include package files
|
||||
|
@ -49,14 +49,14 @@ xxx.xx # in seconds
|
|||
function trainrun(train::Train, path::Path, settings=Settings()::Settings)
|
||||
# prepare the input data
|
||||
movingSection = determineCharacteristics(path, train, settings)
|
||||
settings.outputDetail == :everything && println("The moving section has been prepared.")
|
||||
# settings.outputDetail == :verbose && println("The moving section has been prepared.")
|
||||
|
||||
# calculate the train run for oparation mode "minimum running time"
|
||||
(movingSection, drivingCourse) = calculateMinimumRunningTime!(movingSection, settings, train)
|
||||
settings.outputDetail == :everything && println("The driving course for the shortest running time has been calculated.")
|
||||
# settings.outputDetail == :verbose && println("The driving course for the shortest running time has been calculated.")
|
||||
|
||||
# accumulate data and create an output dictionary
|
||||
output = createOutput(train, settings, path, movingSection, drivingCourse)
|
||||
output = createOutput(settings, path, drivingCourse)
|
||||
|
||||
return output
|
||||
end # function trainrun
|
||||
|
|
|
@ -52,12 +52,12 @@ function Settings(file="DEFAULT")
|
|||
"outputDetail": {
|
||||
"description": "Selecting the detail of the result",
|
||||
"type": "string",
|
||||
"enum": [ "running_time", "points_of_interest", "driving_course", "everything" ]
|
||||
"enum": [ "running_time", "points_of_interest", "driving_course" ]
|
||||
},
|
||||
"outputFormat": {
|
||||
"description": "Output format",
|
||||
"type": "string",
|
||||
"enum": [ "dataframe", "dict" ]
|
||||
"enum": [ "dataframe", "vector" ]
|
||||
}
|
||||
}
|
||||
}""")
|
||||
|
@ -256,7 +256,7 @@ function Path(file, type = :YAML)
|
|||
sort!(tmp_points, by = x -> x[1])
|
||||
for elem in tmp_points
|
||||
station = elem[1] # first point of the section (in m)
|
||||
label = elem[2] # paths speed limt (in m/s)
|
||||
label = elem[2] # paths speed limt (in m/s)
|
||||
measure = elem[3] # specific path resistance of the section (in ‰)
|
||||
|
||||
point = Dict(:station => station,
|
||||
|
@ -302,7 +302,7 @@ function Train(file, type = :YAML)
|
|||
ξ_cars = 1.06 # rotation mass factor
|
||||
transportType = :freight # "freight" or "passenger" for resistance calculation
|
||||
v_limit = 140 # in m/s (default 504 km/h)
|
||||
a_braking = 0 # in m/s^2, todo: implement as function
|
||||
a_braking = 0 # in m/s^2, TODO: implement as function
|
||||
f_Rtd0 = 0 # coefficient for basic resistance due to the traction unit's driving axles (in ‰)
|
||||
f_Rtc0 = 0 # coefficient for basic resistance due to the traction unit's carring axles (in ‰)
|
||||
f_Rt2 = 0 # coefficient for air resistance of the traction unit (in ‰)
|
||||
|
@ -712,7 +712,7 @@ function createDataPoint()
|
|||
:R_train => 0.0, # train resistance (in N)
|
||||
:R_traction => 0.0, # traction unit resistance (in N)
|
||||
:R_wagons => 0.0, # set of wagons resistance (in N)
|
||||
:label => "" # a label for importend points
|
||||
:label => "" # a label for important points
|
||||
)
|
||||
return dataPoint
|
||||
end #function createDataPoint
|
||||
|
|
|
@ -5,15 +5,12 @@
|
|||
# __copyright__ = "2020-2022"
|
||||
# __license__ = "ISC"
|
||||
|
||||
using DataFrames
|
||||
|
||||
function createOutput(train::Train, settings::Settings, path::Path, movingSection::Dict, drivingCourse::Vector{Dict})
|
||||
function createOutput(settings::Settings, path::Path, drivingCourse::Vector{Dict})
|
||||
if settings.outputDetail == :running_time
|
||||
output = drivingCourse[end][:t]
|
||||
output::Vector{Dict} = [Dict(:t => drivingCourse[end][:t])]
|
||||
|
||||
elseif settings.outputDetail == :points_of_interest
|
||||
elseif settings.outputDetail == :points_of_interest && !isempty(path.poi)
|
||||
# add points of interest
|
||||
if !isempty(path.poi)
|
||||
|
||||
# output = Dict[]
|
||||
# POI = 1
|
||||
|
@ -26,79 +23,47 @@ function createOutput(train::Train, settings::Settings, path::Path, movingSectio
|
|||
# i = i+1
|
||||
# end
|
||||
|
||||
# get only the driving course's data points with POI labels
|
||||
output = Dict[]
|
||||
for point in 1:length(drivingCourse)
|
||||
if point[:label] != ""
|
||||
push!(output, point)
|
||||
end
|
||||
# get only the driving course's data points with POI labels
|
||||
output = Dict[]
|
||||
for point in drivingCourse
|
||||
if point[:label] != ""
|
||||
push!(output, point)
|
||||
end
|
||||
end
|
||||
|
||||
elseif settings.outputDetail == :driving_course
|
||||
else #if settings.outputDetail == :driving_course || (settings.outputDetail == :points_of_interest && !isempty(path.poi))
|
||||
output = drivingCourse
|
||||
|
||||
elseif settings.outputDetail == :everything
|
||||
output = Dict{Symbol,Any}()
|
||||
merge!(output, Dict(:train => train, :path => path, :settings => settings))
|
||||
|
||||
|
||||
# add moving section and driving courses
|
||||
merge!(output, Dict(:movingSection => movingSection,
|
||||
:drivingCourse => drivingCourse))
|
||||
|
||||
|
||||
# add points of interest
|
||||
if !isempty(path.poi)
|
||||
pointsOfInterest = Dict[]
|
||||
# get only the driving course's data points with POI labels
|
||||
output = Dict[]
|
||||
for point in 1:length(drivingCourse)
|
||||
if point[:label] != ""
|
||||
push!(pointsOfInterest, point)
|
||||
end
|
||||
end
|
||||
|
||||
merge!(output, Dict(:pointsOfInterest => pointsOfInterest))
|
||||
|
||||
end
|
||||
|
||||
if settings.outputFormat == :dataframe
|
||||
return createDataFrameForDataPoints(output[:drivingCourse])
|
||||
else
|
||||
return output
|
||||
end
|
||||
end
|
||||
|
||||
if settings.outputFormat == :dataframe
|
||||
return createDataFrame(output)
|
||||
else
|
||||
return createDataFrame(output, settings.outputDetail)
|
||||
elseif settings.outputFormat == :vector
|
||||
return output
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function createDataFrame(runningTime::AbstractFloat)
|
||||
# create DataFrame with running time information
|
||||
dataFrame = DataFrame(column1=["t (in s)", runningTime])
|
||||
end
|
||||
function createDataFrame(output_vector::Vector{Dict}, outputDetail)
|
||||
if outputDetail == :running_time
|
||||
# create DataFrame with running time information
|
||||
dataFrame = DataFrame(column1=["t (in s)", output_vector[end][:t]])
|
||||
else # :points_of_interest or :driving_course
|
||||
header = ["label", "driving mode", "s (in m)", "v (in m/s)", "t (in s)", "a (in m/s^2)", "F_T (in N)", "F_R (in N)", "R_path (in N)", "R_traction (in N)", "R_wagons (in N)"]
|
||||
columnSymbols = [:label, :behavior, :s, :v, :t, :a, :F_T, :F_R, :R_path, :R_traction, :R_wagons]
|
||||
|
||||
function createDataFrame(dataPoints::Vector{Dict})
|
||||
header = ["i", "behavior", "station label", "Δs (in m)", "s (in m)", "Δt (in s)","t (in s)","Δv (in m/s)","v (in m/s)","F_T (in N)","F_R (in N)","R_path (in N)","R_train (in N)","R_traction (in N)","R_wagons (in N)","a (in m/s^2)"]
|
||||
columnSymbols = [:i, :behavior, :label, :Δs, :s, :Δt, :t, :Δv, :v, :F_T, :F_R, :R_path, :R_train, :R_traction, :R_wagons, :a]
|
||||
allColumns = Array{Any,1}[]
|
||||
for column in 1:length(header)
|
||||
currentColumn = Any[]
|
||||
push!(currentColumn, header[column])
|
||||
for point in output_vector
|
||||
push!(currentColumn, point[columnSymbols[column]])
|
||||
end
|
||||
push!(allColumns, currentColumn)
|
||||
end # for
|
||||
|
||||
allColumns = Array{Any,1}[]
|
||||
for column in 1:length(header)
|
||||
currentColumn = Any[]
|
||||
push!(currentColumn, header[column])
|
||||
for point in dataPoints
|
||||
push!(currentColumn, point[columnSymbols[column]])
|
||||
end
|
||||
push!(allColumns, currentColumn)
|
||||
end # for
|
||||
|
||||
# combine the columns in a data frame
|
||||
dataFrame = DataFrame(c1=allColumns[1], c2=allColumns[2],c3=allColumns[3], c4=allColumns[4], c5=allColumns[5], c6=allColumns[6], c7=allColumns[7], c8=allColumns[8], c9=allColumns[9], c10=allColumns[10], c11=allColumns[11], c12=allColumns[12], c13=allColumns[13], c14=allColumns[14], c15=allColumns[15], c16=allColumns[16])
|
||||
# combine the columns in a data frame
|
||||
dataFrame = DataFrame(c1=allColumns[1], c2=allColumns[2],c3=allColumns[3], c4=allColumns[4], c5=allColumns[5], c6=allColumns[6], c7=allColumns[7], c8=allColumns[8], c9=allColumns[9], c10=allColumns[10], c11=allColumns[11])
|
||||
end
|
||||
|
||||
return dataFrame
|
||||
end #createDataFrameForDrivingCourse
|
||||
|
|
|
@ -11,9 +11,9 @@ struct Settings
|
|||
stepVariable::Symbol # variable of the linear multistep method: ":distance", ":time" or ":velocity".
|
||||
stepSize::Real # step size, unit depends on stepVariable - :distance in meter, time in seconds and velocity in meter/second.
|
||||
approxLevel::Int # value for approximation; used when rounding or iterating.
|
||||
outputDetail::Symbol # single Float() ":running_time", Array() of ":points_of_interest",
|
||||
# complete Array() ":driving_course", or Dict() ":everything".
|
||||
outputFormat::Symbol # output as ":dataframe" or as ":dict".
|
||||
outputDetail::Symbol # single Float() ":running_time", Vector() of ":points_of_interest",
|
||||
# or complete Vector() ":driving_course"
|
||||
outputFormat::Symbol # output as ":dataframe" or as ":vector".
|
||||
|
||||
end #struct Settings
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
%YAML 1.2
|
||||
---
|
||||
settings:
|
||||
outputDetail: "driving_course" # single value "running_time", array of "points_of_interest",complete array "driving_course", or dict() "everything"
|
||||
outputDetail: "driving_course" # single value "running_time", list of "points_of_interest", complete "driving_course"
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
%YAML 1.2
|
||||
---
|
||||
settings:
|
||||
outputDetail: "everything" # single value "running_time", array of "points_of_interest",complete array "driving_course", or dict() "everything"
|
|
@ -1,4 +1,4 @@
|
|||
%YAML 1.2
|
||||
---
|
||||
settings:
|
||||
outputDetail: "points_of_interest" # single value "running_time", array of "points_of_interest",complete array "driving_course", or dict() "everything"
|
||||
outputDetail: "points_of_interest" # single value "running_time", list of "points_of_interest", complete "driving_course"
|
||||
|
|
|
@ -14,25 +14,24 @@ settings = Dict()
|
|||
@testset "load data" begin
|
||||
|
||||
println("testing load train data")
|
||||
push!(trains, :freight => @time Train("data/trains/freight.yaml"))
|
||||
push!(trains, :local => @time Train("data/trains/local.yaml"))
|
||||
push!(trains, :longdistance => @time Train("data/trains/longdistance.yaml"))
|
||||
push!(trains, :freight => @time Train("test/data/trains/freight.yaml"))
|
||||
push!(trains, :local => @time Train("test/data/trains/local.yaml"))
|
||||
push!(trains, :longdistance => @time Train("test/data/trains/longdistance.yaml"))
|
||||
|
||||
println("testing load path data")
|
||||
push!(paths, :const => @time Path("data/paths/const.yaml"))
|
||||
push!(paths, :slope => @time Path("data/paths/slope.yaml"))
|
||||
push!(paths, :speed => @time Path("data/paths/speed.yaml"))
|
||||
push!(paths, :realworld => @time Path("data/paths/realworld.yaml"))
|
||||
push!(paths, :const => @time Path("test/data/paths/const.yaml"))
|
||||
push!(paths, :slope => @time Path("test/data/paths/slope.yaml"))
|
||||
push!(paths, :speed => @time Path("test/data/paths/speed.yaml"))
|
||||
push!(paths, :realworld => @time Path("test/data/paths/realworld.yaml"))
|
||||
|
||||
println("testing load settings data")
|
||||
push!(settings, "default" => @time Settings())
|
||||
push!(settings, "poi" => @time Settings("data/settings/points_of_interest.yaml"))
|
||||
push!(settings, "drivingcourse" => @time Settings("data/settings/driving_course.yaml"))
|
||||
push!(settings, "everything" => @time Settings("data/settings/everything.yaml"))
|
||||
push!(settings, "strip" => @time Settings("data/settings/strip.yaml"))
|
||||
push!(settings, "time" => @time Settings("data/settings/time.yaml"))
|
||||
push!(settings, "timestrip" => @time Settings("data/settings/time_strip.yaml"))
|
||||
push!(settings, "velocity" => @time Settings("data/settings/velocity.yaml"))
|
||||
push!(settings, "poi" => @time Settings("test/data/settings/points_of_interest.yaml"))
|
||||
push!(settings, "drivingcourse" => @time Settings("test/data/settings/driving_course.yaml"))
|
||||
push!(settings, "strip" => @time Settings("test/data/settings/strip.yaml"))
|
||||
push!(settings, "time" => @time Settings("test/data/settings/time.yaml"))
|
||||
push!(settings, "timestrip" => @time Settings("test/data/settings/time_strip.yaml"))
|
||||
push!(settings, "velocity" => @time Settings("test/data/settings/velocity.yaml"))
|
||||
|
||||
@test typeof(first(paths)[2]) == Path
|
||||
@test typeof(first(settings)[2]) == Settings
|
||||
|
@ -75,7 +74,8 @@ anticipated = Dict(
|
|||
for test in tests
|
||||
test_name = String(test[1][1]) * "_" * String(test[2][1])
|
||||
println("testing $test_name")
|
||||
@time result = trainrun(test[1][2],test[2][2])
|
||||
@time result_dataFrame = trainrun(test[1][2], test[2][2])
|
||||
result = result_dataFrame[!, 1][2]
|
||||
expected = anticipated[:default][Symbol(test_name)]
|
||||
# compare result to test data set
|
||||
@test isapprox(result, expected, rtol=0.01)
|
||||
|
|
Loading…
Reference in New Issue