NREL / routee-compass

An energy-aware routing engine
https://nrel.github.io/routee-compass/
BSD 3-Clause "New" or "Revised" License
10 stars 5 forks source link

Rjf/csv output #168

Closed robfitzgerald closed 6 months ago

robfitzgerald commented 6 months ago

this PR introduces a new CSV output format for RouteE Compass. a user can specify a mapping from JSON dot-delimited paths into CSV column names. for example:

[response_output_policy]
type = "file"
filename = "output.csv"
[response_output_policy.format]
type = "csv"
sorted = true
[response_output_policy.format.mapping]
od_id = "request.name"
dlon = "request.destination_x"
dlat = "request.destination_y"
olon = "request.origin_x"
olat = "request.origin_y"
model_name = "request.model_name"
distance = "traversal_summary.distance"
time = "traversal_summary.time"
energy_electric = { optional = "traversal_summary.energy_electric" }
energy_liquid = { optional = "traversal_summary.energy_electric" }
distance_cost = "cost.distance"
time_cost = "cost.time"
energy_electric_cost = { optional = "cost.energy_electric" }
energy_liquid_cost = { optional = "cost.energy_liquid" }
total_cost = "cost.total_cost"
distance_unit = "state_model.distance.distance_unit"
time_unit = "state_model.time.time_unit"
energy_electic_unit = { optional = "state_model.energy_electric.energy_unit" }
energy_liquid_unit = { optional = "state_model.energy_liquid.energy_unit" }
distance_weight = "request.weights.distance"
time_weight = "request.weights.time"
energy_electric_weight = { optional = "request.weights.energy_electric" }
energy_liquid_weight = { optional = "request.weights.energy_liquid" }

running this with the query in our example notebook produces the following CSV:

distance,distance_cost,distance_unit,distance_weight,dlat,dlon,energy_electic_unit,energy_electric,energy_electric_cost,energy_electric_weight,energy_liquid,energy_liquid_cost,energy_liquid_unit,energy_liquid_weight,model_name,od_id,olat,olon,time,time_cost,time_unit,time_weight,total_cost
6.733433188572938,4.4103987385152745,"miles",0,39.693005,-104.97536,"kilowatt_hours",0.0,0.0,null,0.0,0.7994559767720513,"gallons_gasoline",1,"2016_TOYOTA_Camry_4cyl_2WD","least_energy",39.779021,-104.969307,12.777312852016575,4.21651324116547,"minutes",0,9.426367956452797
9.152878807061885,5.995135618625535,"miles",0,39.693005,-104.97536,"kilowatt_hours",0.0,0.0,null,0.0,0.9603338983361063,"gallons_gasoline",0,"2016_TOYOTA_Camry_4cyl_2WD","least_time",39.779021,-104.969307,10.905464892278664,3.598803414451959,"minutes",1,10.5542729314136
6.470755749159553,4.238345015699507,"miles",1,39.693005,-104.97536,"kilowatt_hours",0.0,0.0,null,0.0,0.8412387893925269,"gallons_gasoline",1,"2016_TOYOTA_Camry_4cyl_2WD","least_cost",39.779021,-104.969307,13.158554513449252,4.342322989438253,"minutes",1,9.421906794530287

details

regular_path = "path.to.value"
optional_path = { optional = "path.to.optional.value" }
sum_path = { sum = [
  "path.to.first",
  "path.to.second"
] }
sum_with_optional = { sum = [
  "path.to.non.optional",
  { optional = "path.to.optional" }
] }

along the way,

Closes #147. Closes #161. Closes #164.

robfitzgerald commented 6 months ago

k, will fix this. it looks like

robfitzgerald commented 6 months ago

i realized this morning our typical use case will actually be a combined output policy, allowing a summary in CSV and the complete output as JSON, so i added that. here's an example:

[response_output_policy]
type = "combined"
[[response_output_policy.policies]]
type = "file"
filename = "output_complete.json"
format = { type = "json", newline_delimited = true }

[[response_output_policy.policies]]
type = "file"
filename = "output_summary.csv"
[response_output_policy.policies.format]
type = "csv"
sorted = true
[response_output_policy.policies.format.mapping]
od_id = "request.name"
dlon = "request.destination_x"
dlat = "request.destination_y"
olon = "request.origin_x"
olat = "request.origin_y"
model_name = "request.model_name"
distance = "traversal_summary.distance"
time = "traversal_summary.time"
energy_electric = { optional = "traversal_summary.energy_electric" }
energy_liquid = { optional = "traversal_summary.energy_electric" }
distance_cost = "cost.distance"
time_cost = "cost.time"
energy_electric_cost = { optional = "cost.energy_electric" }
energy_liquid_cost = { optional = "cost.energy_liquid" }
total_cost = "cost.total_cost"
distance_unit = "state_model.distance.distance_unit"
time_unit = "state_model.time.time_unit"
energy_electic_unit = { optional = "state_model.energy_electric.energy_unit" }
energy_liquid_unit = { optional = "state_model.energy_liquid.energy_unit" }
distance_weight = "request.weights.distance"
time_weight = "request.weights.time"
energy_electric_weight = { optional = "request.weights.energy_electric" }
energy_liquid_weight = { optional = "request.weights.energy_liquid" }
robfitzgerald commented 6 months ago

@nreinicke this has been updated, does it work now for you? also, see note above about combined output policies.