From 2d841e2a2c215a907e4d8a2659313a3ccd2ba199 Mon Sep 17 00:00:00 2001 From: Jens West Date: Mon, 26 Sep 2022 08:50:13 +0300 Subject: [PATCH 1/2] Generalize sub-bound handling --- Scripts/datatypes/purpose.py | 1 + Scripts/datatypes/tour.py | 5 ++--- Scripts/models/logit.py | 12 ++++++------ 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Scripts/datatypes/purpose.py b/Scripts/datatypes/purpose.py index 02f9a81b..35c5ade6 100644 --- a/Scripts/datatypes/purpose.py +++ b/Scripts/datatypes/purpose.py @@ -43,6 +43,7 @@ def __init__(self, specification, zone_data, resultdata=None): sub_intervals = zone_numbers[self.bounds].searchsorted(zone_intervals) self.sub_bounds = [slice(sub_intervals[i-1], sub_intervals[i]) for i in range(1, len(sub_intervals))] + self.sub_intervals = sub_intervals[1:] self.zone_data = zone_data self.resultdata = resultdata self.model = None diff --git a/Scripts/datatypes/tour.py b/Scripts/datatypes/tour.py index 1ce636a9..572ed7ca 100644 --- a/Scripts/datatypes/tour.py +++ b/Scripts/datatypes/tour.py @@ -227,10 +227,9 @@ def _get_cost(self, impedance, mtx_type): pass # scale transit costs from month to day if self.mode == "transit" and mtx_type == "cost": - idx = numpy.searchsorted( - [bounds.stop for bounds in self.purpose.sub_bounds], + i = self.purpose.sub_intervals.searchsorted( self.position[0], side="right") - cost /= transit_trips_per_month[self.purpose.area][demand_type][idx] + cost /= transit_trips_per_month[self.purpose.area][demand_type][i] return cost def __str__(self): diff --git a/Scripts/models/logit.py b/Scripts/models/logit.py index 2caa7e19..22f3923c 100644 --- a/Scripts/models/logit.py +++ b/Scripts/models/logit.py @@ -379,10 +379,10 @@ def calc_individual_mode_prob(self, is_car_user, zone): try: mode_exps[mode] *= math.exp(b["car_users"]) except TypeError: - if zone < self.zone_data.first_surrounding_zone: - mode_exps[mode] *= math.exp(b["car_users"][0]) - else: - mode_exps[mode] *= math.exp(b["car_users"][1]) + # Separate sub-region parameters + i = self.purpose.sub_intervals.searchsorted( + zone, side="right") + mode_exps[mode] *= math.exp(b["car_users"][i]) mode_expsum += mode_exps[mode] probs = numpy.empty(len(modes)) for i, mode in enumerate(modes): @@ -395,8 +395,8 @@ def calc_individual_mode_prob(self, is_car_user, zone): money_utility = 1 / b except TypeError: # Separate sub-region parameters - money_utility = (1 / b[0] if self.sub_bounds[0].stop < zone - else 1 / b[1]) + i = self.purpose.sub_intervals.searchsorted(zone, side="right") + money_utility = 1 / b[i] money_utility /= self.mode_choice_param["car"]["log"]["logsum"] accessibility = -money_utility * logsum return probs, accessibility From e1bc114a26ec54a2912a6560185af0a3e58786d1 Mon Sep 17 00:00:00 2001 From: Jens West Date: Mon, 17 Oct 2022 17:08:48 +0300 Subject: [PATCH 2/2] Fix zone interval for external demand --- Scripts/datahandling/zonedata.py | 29 +++++++++++++++-------------- Scripts/datatypes/purpose.py | 2 +- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/Scripts/datahandling/zonedata.py b/Scripts/datahandling/zonedata.py index d9396035..686ae7a2 100644 --- a/Scripts/datahandling/zonedata.py +++ b/Scripts/datahandling/zonedata.py @@ -13,29 +13,30 @@ class ZoneData: def __init__(self, data_dir, zone_numbers): self._values = {} self.share = ShareChecker(self) - zone_numbers = numpy.array(zone_numbers) + all_zone_numbers = numpy.array(zone_numbers) + self.all_zone_numbers = all_zone_numbers surrounding = param.areas["surrounding"] peripheral = param.areas["peripheral"] external = param.areas["external"] - first_extra = numpy.searchsorted(zone_numbers, peripheral[1], "right") - self.zone_numbers = zone_numbers[:first_extra] + self.zone_numbers = all_zone_numbers[:all_zone_numbers.searchsorted( + peripheral[1], "right")] Zone.counter = 0 self.zones = {number: Zone(number) for number in self.zone_numbers} - self.first_not_helsinki_zone = numpy.searchsorted( - self.zone_numbers, param.municipalities["Espoo"][0]) - self.first_surrounding_zone = numpy.searchsorted( - self.zone_numbers, surrounding[0]) - first_peripheral = numpy.searchsorted(self.zone_numbers, peripheral[0]) + self.first_not_helsinki_zone = self.zone_numbers.searchsorted( + param.municipalities["Espoo"][0]) + self.first_surrounding_zone = self.zone_numbers.searchsorted( + surrounding[0]) + first_peripheral = self.zone_numbers.searchsorted(peripheral[0]) self.first_peripheral_zone = first_peripheral - first_external = numpy.searchsorted(zone_numbers, external[0]) - self.first_external_zone = first_external - external_zones = zone_numbers[first_external:] popdata = read_csv_file(data_dir, ".pop", self.zone_numbers, float) workdata = read_csv_file(data_dir, ".wrk", self.zone_numbers, float) schooldata = read_csv_file(data_dir, ".edu", self.zone_numbers, float) landdata = read_csv_file(data_dir, ".lnd", self.zone_numbers, float) parkdata = read_csv_file(data_dir, ".prk", self.zone_numbers, float) - self.externalgrowth = read_csv_file(data_dir, ".ext", external_zones, float) + self.externalgrowth = read_csv_file( + data_dir, ".ext", + all_zone_numbers[all_zone_numbers.searchsorted(external[0]):], + float) transit = read_csv_file(data_dir, ".tco") try: transit["fare"] = transit["fare"].astype( @@ -69,8 +70,8 @@ def __init__(self, data_dir, zone_numbers): + self["share_age_65-99"]) self.share["share_age_18-99"] = (self["share_age_7-99"] -self["share_age_7-17"]) - self.share["share_female"] = pandas.Series(0.5, zone_numbers) - self.share["share_male"] = pandas.Series(0.5, zone_numbers) + self.share["share_female"] = pandas.Series(0.5, self.zone_numbers) + self.share["share_male"] = pandas.Series(0.5, self.zone_numbers) self.nr_zones = len(self.zone_numbers) self["population_density"] = pop / landdata["builtar"] wp = workdata["total"] diff --git a/Scripts/datatypes/purpose.py b/Scripts/datatypes/purpose.py index 35c5ade6..c636871c 100644 --- a/Scripts/datatypes/purpose.py +++ b/Scripts/datatypes/purpose.py @@ -36,7 +36,7 @@ def __init__(self, specification, zone_data, resultdata=None): self.dest = specification["dest"] self.area = specification["area"] self.sources = [] - zone_numbers = zone_data.zone_numbers + zone_numbers = zone_data.all_zone_numbers zone_intervals = param.purpose_areas[self.area] self.bounds = slice(*zone_numbers.searchsorted( [zone_intervals[0], zone_intervals[-1]]))