Skip to content

Commit

Permalink
Agent tours to separate file (#308)
Browse files Browse the repository at this point in the history
* Agent tours to separate file

Option to write agent data using separate file for tours. Separate persons and trip tables is common way of storing travel survey data.

+ More flexible analysis possibilities in R. Therefore no need to change Helmet model system, if extra analysis is needed.
- Consumes more hard disk space (from ~100 MB to 200 MB).

* Remove Try - Except

* Looping to first person with tours handles persons with no tours (Try - Except not needed)

* Add purpose name to tour data

* Use class attributes as headers

* No need to loop over objects as reference can be made directly to class variables

Co-authored-by: Jens West <[email protected]>
  • Loading branch information
attesn and Jens West authored May 31, 2021
1 parent e76844c commit 12e6c98
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 21 deletions.
21 changes: 6 additions & 15 deletions Scripts/datatypes/person.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,9 @@ class Person:
id_counter = 0
FEMALE = 0
MALE = 1
person_attr = ["id", "age_group", "gender", "is_car_user", "income", "nr_tours"]
person_attr = ["id", "age_group", "gender", "is_car_user", "income"]
zone_attr = ["number", "area", "municipality"]
tour_attr = ["total_access", "sustainable_access"]
attr = person_attr + zone_attr + tour_attr
attr = person_attr + zone_attr

def __init__(self, zone, age_group,
generation_model, car_use_model, income_model):
Expand Down Expand Up @@ -113,19 +112,18 @@ def add_tours(self, purposes, tour_probs):
pass
# Tours that were not recycled, will be created
for key in new_tours:
tour = Tour(purposes[key], self.zone)
tour = Tour(purposes[key], self.zone, self.id)
self.tours.append(tour)
if key == "hw":
non_home_prob = purposes["wo"].gen_model.param[key]
if random.random() < non_home_prob:
non_home_tour = Tour(purposes["wo"], tour)
non_home_tour = Tour(purposes["wo"], tour, self.id)
self.tours.append(non_home_tour)
else:
non_home_prob = purposes["oo"].gen_model.param[key]
if random.random() < non_home_prob:
non_home_tour = Tour(purposes["oo"], tour)
non_home_tour = Tour(purposes["oo"], tour, self.id)
self.tours.append(non_home_tour)
self.nr_tours = len(self.tours)

def __str__(self):
""" Return person attributes as string.
Expand All @@ -135,13 +133,6 @@ def __str__(self):
str
Person object attributes.
"""
# sum accessibility of all tours
tour_attributes = dict.fromkeys(Person.tour_attr, 0)
for tour in self.tours:
for attr in tour_attributes:
tour_attributes[attr] += getattr(tour, attr)
# print to file
persondata = [str(getattr(self, attr)) for attr in Person.person_attr]
zonedata = [str(getattr(self.zone, attr)) for attr in Person.zone_attr]
tourdata = [str(tour_attributes[attr]) for attr in Person.tour_attr]
return "\t".join(persondata + zonedata + tourdata)
return "\t".join(persondata + zonedata)
17 changes: 16 additions & 1 deletion Scripts/datatypes/tour.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,13 @@ class Tour(object):
"""
# Expansion factor used on demand in departure time model
matrix = numpy.array([[1 / zone_param.agent_demand_fraction]])
attr = ["person_id", "purpose_name", "mode",
"total_access", "sustainable_access"]

def __init__(self, purpose, origin):
def __init__(self, purpose, origin, person_id):
self.person_id = person_id
self.purpose = purpose
self.purpose_name = purpose.name
self.orig = origin
try:
self.sec_dest_prob = purpose.sec_dest_purpose.gen_model.param[purpose.name]
Expand Down Expand Up @@ -175,3 +179,14 @@ def choose_secondary_destination(self, cumulative_probs):
+ numpy.searchsorted(cumulative_probs, self._sec_dest_draw))
self.position = (self.position[0], self.position[1], dest_idx)
self.purpose.sec_dest_purpose.attracted_tours[self.mode][dest_idx] += 1

def __str__(self):
""" Return tour attributes as string.
Returns
----------
str
Tour object attributes.
"""
tourdata = [str(getattr(self, attr)) for attr in Tour.attr]
return "\t".join(tourdata)
17 changes: 12 additions & 5 deletions Scripts/modelsystem.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
from demand.trips import DemandModel
from demand.external import ExternalModel
from datatypes.purpose import SecDestPurpose
from datatypes.person import Person
from datatypes.tour import Tour
from transform.impedance_transformer import ImpedanceTransformer
from models.linear import CarDensityModel
import parameters.assignment as param
Expand Down Expand Up @@ -558,13 +560,18 @@ def _add_internal_demand(self, previous_iter_impedance, is_last_iteration):
random.seed(zone_param.population_draw)
self.dm.predict_income()
random.seed(None)
fname = "agents"
header = "\t".join(self.dm.population[0].attr)
self.resultdata.print_line(header, fname)
fname0 = "agents"
fname1 = "tours"
# print person and tour attr to files
self.resultdata.print_line("\t".join(Person.attr), fname0)
self.resultdata.print_line("\t".join(Tour.attr), fname1)
for person in self.dm.population:
person.calc_income()
self.resultdata.print_line(str(person), fname)
log.info("Results printed to file ".format(fname))
self.resultdata.print_line(str(person), fname0)
for tour in person.tours:
self.resultdata.print_line(str(tour), fname1)
log.info("Results printed to files {} and {}".format(
fname0, fname1))
log.info("Demand calculation completed")

def _distribute_tours(self, mode, origs, sec_dest_tours, impedance):
Expand Down

0 comments on commit 12e6c98

Please sign in to comment.