Skip to content

Commit b961e64

Browse files
Merge pull request #43 from simulate-digital-rail/json-import
add basic from_json() implementation to topology
2 parents c094084 + 4a6cd1b commit b961e64

File tree

9 files changed

+244
-63
lines changed

9 files changed

+244
-63
lines changed

poetry.lock

Lines changed: 148 additions & 49 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
[tool.poetry]
22
name = "yaramo"
3-
version = "0.1.1"
3+
version = "0.2"
44
description = "yaramo is a railway model focusing on interoperability between different existing planning formats."
55
authors = ["OSM at HPI <arne.boockmeyer@hpi.de>"]
66
readme = "README.md"
77
packages = [{include = "yaramo"}]
88

99
[tool.poetry.dependencies]
10-
python = "^3.8"
11-
pyproj = "^3.4.1"
10+
python = "^3.9"
11+
pyproj = "^3.6.1"
12+
simplejson = "^3.19.2"
1213

1314

1415
[tool.poetry.group.dev.dependencies]

test/topology_test.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,22 @@ def _test_edge(_node_a, _node_b, _expected_edge):
2323
_test_edge(node_a, node_b, edge)
2424
_test_edge(node_b, node_a, edge)
2525
_test_edge(node_a, node_c, None)
26+
27+
28+
def test_json_export_and_import():
29+
topology = Topology()
30+
31+
node_a = Node()
32+
node_b = Node()
33+
topology.add_node(node_a)
34+
topology.add_node(node_b)
35+
edge = Edge(node_a, node_b)
36+
topology.add_edge(edge)
37+
38+
json_str = topology.to_json()
39+
topology_copy = Topology.from_json(json_str)
40+
41+
assert len(topology.nodes) == len(topology_copy.nodes)
42+
assert len(topology.edges) == len(topology_copy.edges)
43+
assert len(topology.signals) == len(topology_copy.signals)
44+
assert len(topology.routes) == len(topology_copy.routes)

yaramo/base_element.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
import json
21
from typing import Tuple
32
from uuid import uuid4
43

4+
import simplejson as json
5+
56

67
class BaseElement(object):
78
def __init__(self, uuid: str = None, name: str = None, **kwargs) -> None:
@@ -26,4 +27,4 @@ def to_serializable(self) -> Tuple[dict, dict]:
2627
return self.__dict__, {}
2728

2829
def to_json(self) -> str:
29-
return json.dumps(self.to_serializable()[0])
30+
return json.dumps(self.to_serializable()[0], iterable_as_array=True)

yaramo/edge.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ def __init__(
2121
node_b: Node,
2222
vacancy_section: Optional[VacancySection] = None,
2323
length: float = None,
24+
intermediate_geo_nodes: List[GeoNode] = None,
25+
signals: list["Signal"] = None,
26+
maximum_speed: int = None,
2427
**kwargs
2528
):
2629
"""
@@ -37,12 +40,12 @@ def __init__(
3740
"""
3841

3942
super().__init__(**kwargs)
43+
self.intermediate_geo_nodes = intermediate_geo_nodes or []
4044
self.node_a = node_a
4145
self.node_b = node_b
42-
self.intermediate_geo_nodes: list[GeoNode] = []
43-
self.signals: list[Signal] = []
46+
self.signals = signals or []
4447
self.length = length
45-
self.maximum_speed: int = None
48+
self.maximum_speed = maximum_speed
4649
self.vacancy_section = vacancy_section
4750

4851
def is_node_connected(self, other_node) -> bool:
@@ -143,7 +146,7 @@ def to_serializable(self):
143146
"intermediate_geo_nodes": [geo_node.uuid for geo_node in self.intermediate_geo_nodes],
144147
"signals": [signal.uuid for signal in self.signals],
145148
}
146-
objects = {}
149+
objects = dict()
147150
for geo_node in self.intermediate_geo_nodes:
148151
geo_node_object, serialized_geo_node = geo_node.to_serializable()
149152
objects = {**objects, geo_node.uuid: geo_node_object, **serialized_geo_node}

yaramo/geo_point.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ def get_distance_to_other_geo_point(self, geo_point_b: "Wgs84GeoPoint"):
4242
return self.__haversine_distance(geo_point_b) / 1000
4343

4444
def __haversine_distance(self, geo_point_b: "GeoPoint"):
45-
pi_over_180 = Decimal(math.pi / 180)
45+
pi_over_180 = float(math.pi / 180)
4646
return (
4747
2
4848
* 6371000

yaramo/node.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ def __init__(self, turnout_side=None, **kwargs):
3737
self.maximum_speed_on_left = None
3838
self.maximum_speed_on_right = None
3939
self.connected_nodes: list["Node"] = []
40-
self.geo_node: GeoNode = None
40+
self.geo_node: GeoNode = kwargs.get("geo_node", None)
4141
self.turnout_side: str = turnout_side
4242

4343
def maximum_speed(self, node_a: "Node", node_b: "Node"):
@@ -182,7 +182,7 @@ def to_serializable(self):
182182
"connected_nodes": [node.uuid for node in self.connected_nodes],
183183
"geo_node": self.geo_node.uuid if self.geo_node else None,
184184
}
185-
objects = {}
185+
objects = dict()
186186
if self.geo_node:
187187
geo_node, serialized_geo_node = self.geo_node.to_serializable()
188188
objects = {**objects, self.geo_node.uuid: geo_node, **serialized_geo_node}

yaramo/signal.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,12 +142,13 @@ def to_serializable(self) -> Tuple[dict, dict]:
142142
"edge": self.edge.uuid if self.edge else None,
143143
"trip": self.trip.uuid if self.trip else None,
144144
"additional_signals": [signal.uuid for signal in self.additional_signals],
145+
"supported_states": [str(state) for state in self.supported_states],
145146
"direction": str(self.direction),
146147
"side_distance": self.side_distance,
147148
"function": str(self.function),
148149
"kind": str(self.kind),
149150
}
150-
objects = {}
151+
objects = dict()
151152
items = [self.trip] + self.additional_signals if self.trip else self.additional_signals
152153
for item in items:
153154
item_object, serialized_item = item.to_serializable()

yaramo/topology.py

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1+
import simplejson as json
2+
13
from yaramo.base_element import BaseElement
24
from yaramo.edge import Edge
5+
from yaramo.geo_node import Wgs84GeoNode
36
from yaramo.node import Node
47
from yaramo.route import Route
58
from yaramo.signal import Signal
@@ -54,7 +57,7 @@ def to_serializable(self):
5457
A serializable dictionary of all the objects belonging to the Topology.
5558
"""
5659
nodes, edges, signals, routes, vacancy_sections = [], [], [], [], []
57-
objects = {}
60+
objects = dict()
5861

5962
for items, _list in [
6063
(list(self.signals.values()), signals),
@@ -76,3 +79,57 @@ def to_serializable(self):
7679
"objects": objects,
7780
"vacany_sections": vacancy_sections,
7881
}, {}
82+
83+
@classmethod
84+
def from_json(cls, json_str: str):
85+
obj = json.loads(json_str)
86+
topology = cls()
87+
for node in obj["nodes"]:
88+
node_obj = Node(**node)
89+
topology.add_node(node_obj)
90+
if "geo_node" in node and node["geo_node"] is not None:
91+
geo_node = obj["objects"][node["geo_node"]]
92+
geo_node_obj = Wgs84GeoNode(
93+
obj["objects"][geo_node["geo_point"]]["x"],
94+
obj["objects"][geo_node["geo_point"]]["y"],
95+
name=geo_node["name"],
96+
uuid=geo_node["uuid"],
97+
)
98+
node_obj.geo_node = geo_node_obj
99+
100+
for signal in obj["signals"]:
101+
topology.add_signal(Signal(**signal))
102+
for edge in obj["edges"]:
103+
node_a = topology.nodes[edge["node_a"]]
104+
node_b = topology.nodes[edge["node_b"]]
105+
node_a.connected_nodes.append(node_b)
106+
node_b.connected_nodes.append(node_a)
107+
geo_node_strings = [
108+
obj["objects"][geo_node_uuid]
109+
for geo_node_uuid in edge["intermediate_geo_nodes"]
110+
if geo_node_uuid in obj["objects"]
111+
]
112+
topology.add_edge(
113+
Edge(
114+
**{
115+
**edge,
116+
"node_a": node_a,
117+
"node_b": node_b,
118+
"signals": [
119+
topology.signals[signal_uuid] for signal_uuid in edge["signals"]
120+
],
121+
"intermediate_geo_nodes": [
122+
Wgs84GeoNode(
123+
obj["objects"][geo_node["geo_point"]]["x"],
124+
obj["objects"][geo_node["geo_point"]]["y"],
125+
name=geo_node["name"],
126+
uuid=geo_node["uuid"],
127+
)
128+
for geo_node in geo_node_strings
129+
],
130+
}
131+
)
132+
)
133+
for signal in obj["signals"]:
134+
topology.signals[signal["uuid"]].edge = topology.edges[signal["edge"]]
135+
return topology

0 commit comments

Comments
 (0)