MATSim Plans - Sequence to Score¶
Demo of parsing MATSim (experienced) plans for a sequence to score model.
MATSim plans from multiple iterations are processed into plan-scores.
Note that this extracts plan activities and trips. Each sequence component includes duration, model and distance.
In [1]:
Copied!
from pathlib import Path
import pandas as pd
from pam.read.matsim import load_attributes_map_from_v12, stream_matsim_persons
from pam.utils import datetime_to_matsim_time
from pam.core import Population, Person
from pam.activity import Activity, Plan, Leg
from pathlib import Path
import pandas as pd
from pam.read.matsim import load_attributes_map_from_v12, stream_matsim_persons
from pam.utils import datetime_to_matsim_time
from pam.core import Population, Person
from pam.activity import Activity, Plan, Leg
In [15]:
Copied!
dir = Path("data/matsim")
# input paths
output_plans_path = dir / "output_plans.xml"
iter_50 = dir / "output_experienced_plans_ITER50.xml"
assert iter_50.exists()
iter_100 = dir / "output_experienced_plans_ITER100.xml"
assert iter_100.exists()
iter_150 = dir / "output_experienced_plans_ITER150.xml"
assert iter_150.exists()
# output path
output_dir = Path("tmp")
output_dir.mkdir(exist_ok=True)
schedules_path = output_dir / "combined.csv"
attributes_path = output_dir / "attributes.csv"
dir = Path("data/matsim")
# input paths
output_plans_path = dir / "output_plans.xml"
iter_50 = dir / "output_experienced_plans_ITER50.xml"
assert iter_50.exists()
iter_100 = dir / "output_experienced_plans_ITER100.xml"
assert iter_100.exists()
iter_150 = dir / "output_experienced_plans_ITER150.xml"
assert iter_150.exists()
# output path
output_dir = Path("tmp")
output_dir.mkdir(exist_ok=True)
schedules_path = output_dir / "combined.csv"
attributes_path = output_dir / "attributes.csv"
In [16]:
Copied!
streamer50 = stream_matsim_persons(
iter_50,
simplify_pt_trips=True,
# crop=True,
keep_non_selected=False,
leg_attributes=True,
leg_route=True,
)
streamer100 = stream_matsim_persons(
iter_100,
simplify_pt_trips=True,
# crop=True,
keep_non_selected=False,
leg_attributes=True,
leg_route=True,
)
streamer150 = stream_matsim_persons(
iter_150,
simplify_pt_trips=True,
# crop=True,
keep_non_selected=False,
leg_attributes=True,
leg_route=True,
)
streamers = [streamer50, streamer100, streamer150]
streamer50 = stream_matsim_persons(
iter_50,
simplify_pt_trips=True,
# crop=True,
keep_non_selected=False,
leg_attributes=True,
leg_route=True,
)
streamer100 = stream_matsim_persons(
iter_100,
simplify_pt_trips=True,
# crop=True,
keep_non_selected=False,
leg_attributes=True,
leg_route=True,
)
streamer150 = stream_matsim_persons(
iter_150,
simplify_pt_trips=True,
# crop=True,
keep_non_selected=False,
leg_attributes=True,
leg_route=True,
)
streamers = [streamer50, streamer100, streamer150]
In [17]:
Copied!
def dt_to_min(dt) -> int:
h, m, s = datetime_to_matsim_time(dt).split(":")
return (int(h) * 60) + int(m)
def person_to_schedule(person: Person) -> tuple:
score = person.plan.score
record = []
for component in person.plan:
if isinstance(component, Leg):
distance = component.euclidean_distance
mode = component.mode
else:
distance = 0
mode = "NA"
record.append(
[
component.act,
dt_to_min(component.start_time),
dt_to_min(component.end_time),
mode,
distance,
score,
]
)
return person.pid, record
def add_data(record, pid, iteration):
record = [[pid, iteration] + line for line in record]
return record
def dt_to_min(dt) -> int:
h, m, s = datetime_to_matsim_time(dt).split(":")
return (int(h) * 60) + int(m)
def person_to_schedule(person: Person) -> tuple:
score = person.plan.score
record = []
for component in person.plan:
if isinstance(component, Leg):
distance = component.euclidean_distance
mode = component.mode
else:
distance = 0
mode = "NA"
record.append(
[
component.act,
dt_to_min(component.start_time),
dt_to_min(component.end_time),
mode,
distance,
score,
]
)
return person.pid, record
def add_data(record, pid, iteration):
record = [[pid, iteration] + line for line in record]
return record
In [18]:
Copied!
schedules = []
uid = 0
mapper = {}
for iteration, streamer in zip([50, 100, 150], streamers):
print("iteration: ", iteration)
for person in streamer:
pid, record = person_to_schedule(person)
if record:
mapper[uid] = pid
schedules.extend(add_data(record, uid, iteration))
uid += 1
schedules = pd.DataFrame(
schedules,
columns=["pid", "iter", "act", "start", "end", "mode", "distance", "score"],
).set_index("pid")
schedules = []
uid = 0
mapper = {}
for iteration, streamer in zip([50, 100, 150], streamers):
print("iteration: ", iteration)
for person in streamer:
pid, record = person_to_schedule(person)
if record:
mapper[uid] = pid
schedules.extend(add_data(record, uid, iteration))
uid += 1
schedules = pd.DataFrame(
schedules,
columns=["pid", "iter", "act", "start", "end", "mode", "distance", "score"],
).set_index("pid")
iteration: 50 iteration: 100 iteration: 150
In [19]:
Copied!
attributes = load_attributes_map_from_v12(output_plans_path)
attributes = {k: attributes[v] for k, v in mapper.items()}
attributes = pd.DataFrame(attributes).T
attributes.index.name = "pid"
attributes = attributes.fillna("unknown")
attributes.head()
attributes = load_attributes_map_from_v12(output_plans_path)
attributes = {k: attributes[v] for k, v in mapper.items()}
attributes = pd.DataFrame(attributes).T
attributes.index.name = "pid"
attributes = attributes.fillna("unknown")
attributes.head()
Out[19]:
subpopulation | age | |
---|---|---|
pid | ||
0 | rich | yes |
1 | poor | no |
2 | poor | no |
3 | poor | no |
4 | poor | no |
In [20]:
Copied!
schedules.to_csv(schedules_path)
attributes.to_csv(attributes_path)
schedules.to_csv(schedules_path)
attributes.to_csv(attributes_path)