diff --git a/in/example.stat.xml b/in/example.stat.xml
index ece9fec..f8302a6 100644
--- a/in/example.stat.xml
+++ b/in/example.stat.xml
@@ -1,18 +1,4 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
\ No newline at end of file
diff --git a/perlin.py b/perlin.py
index b63fbea..4ee1173 100644
--- a/perlin.py
+++ b/perlin.py
@@ -20,9 +20,9 @@
# The 'noise' lib has good resolution until above 10 mil, but a SIGSEGV is had on values above [-100000, 100000]
# FIXME: these values result in a noisemap which contains CRT-like lines and patterns. Find better, sane values.
# POPULATION_BASE = random.randrange(-1000, 1000)
-POPULATION_BASE: float = 0
+POPULATION_BASE = 4
# INDUSTRY_BASE = random.randrange(-1000, 1000)
-INDUSTRY_BASE: float = 0
+INDUSTRY_BASE = 1
def get_edge_pair_centroid(coords: List[Tuple[float, float]]) -> (float, float):
@@ -36,7 +36,7 @@ def get_edge_pair_centroid(coords: List[Tuple[float, float]]) -> (float, float):
return x_avg, y_avg
-def get_perlin_noise(x: float, y: float, base: float, scale: float = 0.005, octaves: int = 3) -> float:
+def get_perlin_noise(x: float, y: float, base: int, scale: float = 0.005, octaves: int = 3) -> float:
"""
The 'noise' lib returns a value in the range of [-1:1]. The noise value is scaled to the range of [0:1].
:param base: offset into noisemap
@@ -49,7 +49,7 @@ def get_perlin_noise(x: float, y: float, base: float, scale: float = 0.005, octa
return (noise.pnoise2(x=x * scale, y=y * scale, octaves=octaves, base=base) + 1) / 2
-def get_population_number(edge: sumolib.net.edge.Edge, base: float, centre,
+def get_population_number(edge: sumolib.net.edge.Edge, base: int, centre,
radius, scale: float = 0.005, octaves: int = 3) -> float:
"""
Returns a Perlin simplex noise at centre of given street
diff --git a/randomActivityGen.py b/randomActivityGen.py
index 77f4ab1..3c28c08 100644
--- a/randomActivityGen.py
+++ b/randomActivityGen.py
@@ -100,7 +100,45 @@ def setup_city_gates(net: sumolib.net.Net, stats: ET.ElementTree, gate_count: in
})
-if __name__ == "__main__":
+def verify_stats(stats: ET.ElementTree):
+ """
+ Do various verification on the stats file to ensure that it is usable. If population and work hours are missing,
+ some default values will be insert as these are required by ActivityGen.
+
+ :param stats: stats file parsed with ElementTree
+ """
+ city = stats.getroot()
+ assert city.tag == "city", "Stat file does not seem to be a valid stat file. The root element is not city"
+ # According to ActivityGen (https://github.com/eclipse/sumo/blob/master/src/activitygen/AGActivityGenHandler.cpp#L124-L161)
+ # only general::inhabitants and general::households are required. Everything else has default values.
+ general = stats.find("general")
+ # TODO Maybe guestimate the number of inhabitants and households based on the network's size
+ assert general is not None, "Stat file is missing . Inhabitants and households are required"
+ assert general.attrib["inhabitants"] is not None, "Number of inhabitants are required"
+ assert general.attrib["households"] is not None, "Number of households are required"
+
+ # It is also required that there are at least one population bracket
+ population = city.find("population")
+ if population is None:
+ # Population is missing, so we add a default population
+ population = ET.SubElement(city, "population")
+ ET.SubElement(population, "bracket", {"beginAge": "0", "endAge": "30", "peopleNbr": "30"})
+ ET.SubElement(population, "bracket", {"beginAge": "30", "endAge": "60", "peopleNbr": "40"})
+ ET.SubElement(population, "bracket", {"beginAge": "60", "endAge": "90", "peopleNbr": "30"})
+
+ # Similarly at least and one opening and closing workhour is required
+ work_hours = city.find("workHours")
+ if work_hours is None:
+ # Work hours are missing, so we add some default work hours
+ work_hours = ET.SubElement(city, "workHours")
+ ET.SubElement(work_hours, "opening", {"hour": "28800", "proportion": "70"}) # 70% at 8.00
+ ET.SubElement(work_hours, "opening", {"hour": "30600", "proportion": "30"}) # 30% at 8.30
+ ET.SubElement(work_hours, "closing", {"hour": "43200", "proportion": "10"}) # 10% at 12.00
+ ET.SubElement(work_hours, "closing", {"hour": "61200", "proportion": "30"}) # 30% at 17.00
+ ET.SubElement(work_hours, "closing", {"hour": "63000", "proportion": "60"}) # 60% at 17.30
+
+
+def main():
args = docopt(__doc__, version="RandomActivityGen v0.1")
# Read in SUMO network
@@ -108,6 +146,7 @@ def setup_city_gates(net: sumolib.net.Net, stats: ET.ElementTree, gate_count: in
# Parse statistics configuration
stats = ET.parse(args["--stat-file"])
+ verify_stats(stats)
# Scale and octave seems like sane values for the moment
apply_network_noise(net, stats, 0.005, 3)
@@ -116,3 +155,7 @@ def setup_city_gates(net: sumolib.net.Net, stats: ET.ElementTree, gate_count: in
# Write statistics back
stats.write(args["--output-file"])
+
+
+if __name__ == "__main__":
+ main()