plexus-python-pulse-common 1.1.79__tar.gz → 1.1.81__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/PKG-INFO +1 -1
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/src/plexus/pulse/common/carto/OSMFile.py +39 -39
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/src/plexus/pulse/common/carto/OSMNode.py +4 -4
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/src/plexus/pulse/common/carto/OSMTags.py +5 -5
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/src/plexus/pulse/common/carto/OSMWay.py +4 -4
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/src/plexus/pulse/common/utils/bagutils.py +14 -14
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/src/plexus/pulse/common/utils/gisutils.py +52 -52
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/src/plexus/pulse/common/utils/pathutils.py +13 -17
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/src/plexus/pulse/common/utils/s3utils.py +34 -33
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/src/plexus/pulse/common/utils/tagutils.py +272 -152
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/src/plexus_python_pulse_common.egg-info/PKG-INFO +1 -1
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/.editorconfig +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/.github/workflows/pr.yml +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/.github/workflows/push.yml +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/.gitignore +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/MANIFEST.in +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/README.md +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/VERSION +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/pyproject.toml +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/resources/unittest/jsonutils/dummy.0.jsonl +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/resources/unittest/jsonutils/dummy.1.jsonl +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/resources/unittest/jsonutils/dummy.2.jsonl +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/resources/unittest/pathutils/0-dummy +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/resources/unittest/pathutils/1-dummy +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/resources/unittest/pathutils/2-dummy +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/resources/unittest/pathutils/dummy.0.0.jsonl +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/resources/unittest/pathutils/dummy.0.0.vol-0.jsonl +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/resources/unittest/pathutils/dummy.0.jsonl +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/resources/unittest/pathutils/dummy.1.1.jsonl +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/resources/unittest/pathutils/dummy.1.1.vol-1.jsonl +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/resources/unittest/pathutils/dummy.1.jsonl +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/resources/unittest/pathutils/dummy.2.2.jsonl +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/resources/unittest/pathutils/dummy.2.2.vol-2.jsonl +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/resources/unittest/pathutils/dummy.2.jsonl +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/resources/unittest/pathutils/dummy.csv.part0 +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/resources/unittest/pathutils/dummy.csv.part1 +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/resources/unittest/pathutils/dummy.csv.part2 +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/resources/unittest/pathutils/dummy.txt +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/resources/unittest/s3utils/dir.baz/file.bar.baz +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/resources/unittest/s3utils/dir.baz/file.foo.bar +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/resources/unittest/s3utils/dir.baz/file.foo.baz +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/resources/unittest/s3utils/dir.foo/dir.foo.bar/dir.foo.bar.baz/file.foo.bar.baz +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/resources/unittest/s3utils/dir.foo/dir.foo.bar/file.bar.baz +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/resources/unittest/s3utils/dir.foo/dir.foo.bar/file.foo.bar +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/resources/unittest/s3utils/dir.foo/dir.foo.bar/file.foo.baz +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/resources/unittest/s3utils/dir.foo/file.bar +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/resources/unittest/s3utils/dir.foo/file.baz +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/resources/unittest/s3utils/dir.foo/file.foo +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/resources/unittest/s3utils_archive/archive.compressed.zip +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/resources/unittest/s3utils_archive/archive.uncompressed.zip +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/setup.cfg +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/setup.py +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/src/plexus/pulse/common/__init__.py +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/src/plexus/pulse/common/carto/__init__.py +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/src/plexus/pulse/common/resources/__init__.py +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/src/plexus/pulse/common/resources/tags/__init__.py +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/src/plexus/pulse/common/resources/tags/unittest-1.0.0.tagset.yaml +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/src/plexus/pulse/common/resources/tags/universal-1.0.0.tagset.yaml +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/src/plexus/pulse/common/utils/__init__.py +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/src/plexus/pulse/common/utils/apiutils.py +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/src/plexus/pulse/common/utils/config.py +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/src/plexus/pulse/common/utils/datautils.py +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/src/plexus/pulse/common/utils/dockerutils.py +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/src/plexus/pulse/common/utils/flowutils.py +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/src/plexus/pulse/common/utils/jsonutils.py +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/src/plexus/pulse/common/utils/ormutils.py +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/src/plexus/pulse/common/utils/sqlutils.py +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/src/plexus/pulse/common/utils/strutils.py +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/src/plexus/pulse/common/utils/testutils.py +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/src/plexus_python_pulse_common.egg-info/SOURCES.txt +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/src/plexus_python_pulse_common.egg-info/dependency_links.txt +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/src/plexus_python_pulse_common.egg-info/not-zip-safe +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/src/plexus_python_pulse_common.egg-info/requires.txt +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/src/plexus_python_pulse_common.egg-info/top_level.txt +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/test/plexus_tests/__init__.py +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/test/plexus_tests/pulse/__init__.py +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/test/plexus_tests/pulse/common/__init__.py +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/test/plexus_tests/pulse/common/carto/__init__.py +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/test/plexus_tests/pulse/common/carto/osm_file_test.py +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/test/plexus_tests/pulse/common/carto/osm_tags_test.py +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/test/plexus_tests/pulse/common/utils/__init__.py +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/test/plexus_tests/pulse/common/utils/bagutils_test.py +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/test/plexus_tests/pulse/common/utils/datautils_test.py +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/test/plexus_tests/pulse/common/utils/dockerutils_test.py +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/test/plexus_tests/pulse/common/utils/flowutils_test.py +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/test/plexus_tests/pulse/common/utils/gisutils_test.py +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/test/plexus_tests/pulse/common/utils/jsonutils_test.py +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/test/plexus_tests/pulse/common/utils/ormutils_test.py +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/test/plexus_tests/pulse/common/utils/pathutils_test.py +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/test/plexus_tests/pulse/common/utils/s3utils_test.py +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/test/plexus_tests/pulse/common/utils/strutils_test.py +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/test/plexus_tests/pulse/common/utils/tagutils_test.py +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/test/plexus_tests/pulse/common/utils/testutils_test.py +0 -0
- {plexus_python_pulse_common-1.1.79 → plexus_python_pulse_common-1.1.81}/test/testenv.py +0 -0
|
@@ -12,12 +12,12 @@ class OSMFile(object):
|
|
|
12
12
|
@classmethod
|
|
13
13
|
def load_file(cls, path: str, proj: Proj | None) -> Self:
|
|
14
14
|
"""
|
|
15
|
-
Loads OSM from
|
|
15
|
+
Loads an OSM file from the given path.
|
|
16
16
|
|
|
17
|
-
:param path:
|
|
18
|
-
:param proj:
|
|
17
|
+
:param path: Path to the OSM file.
|
|
18
|
+
:param proj: Cartographic projection to use for coordinates.
|
|
19
19
|
|
|
20
|
-
:return:
|
|
20
|
+
:return: Loaded OSM file.
|
|
21
21
|
"""
|
|
22
22
|
root = lxml.etree.parse(path).getroot()
|
|
23
23
|
|
|
@@ -71,12 +71,12 @@ class OSMFile(object):
|
|
|
71
71
|
@classmethod
|
|
72
72
|
def from_coords(cls, coords: list[Coord], way_tags: dict[str, Any] = None) -> Self:
|
|
73
73
|
"""
|
|
74
|
-
Constructs a single-way OSM file from the given
|
|
74
|
+
Constructs a single-way OSM file from the given coordinates.
|
|
75
75
|
|
|
76
|
-
:param coords:
|
|
77
|
-
:param way_tags:
|
|
76
|
+
:param coords: Coordinates that make up the way.
|
|
77
|
+
:param way_tags: Tags to assign to the way.
|
|
78
78
|
|
|
79
|
-
:return: OSM file
|
|
79
|
+
:return: OSM file containing one way.
|
|
80
80
|
"""
|
|
81
81
|
osm = OSMFile()
|
|
82
82
|
osm.add_way_from_coords(coords, way_tags or {})
|
|
@@ -86,12 +86,12 @@ class OSMFile(object):
|
|
|
86
86
|
@classmethod
|
|
87
87
|
def from_coords_list(cls, coords_list: list[list[Coord]], way_tags_list: list[dict[str, Any]] = None) -> Self:
|
|
88
88
|
"""
|
|
89
|
-
Constructs a multi-way OSM file from the given
|
|
89
|
+
Constructs a multi-way OSM file from the given coordinate lists.
|
|
90
90
|
|
|
91
|
-
:param coords_list:
|
|
92
|
-
:param way_tags_list:
|
|
91
|
+
:param coords_list: Coordinates for each way.
|
|
92
|
+
:param way_tags_list: Tags to assign to each corresponding way.
|
|
93
93
|
|
|
94
|
-
:return: OSM file
|
|
94
|
+
:return: OSM file containing multiple ways.
|
|
95
95
|
"""
|
|
96
96
|
osm = OSMFile()
|
|
97
97
|
|
|
@@ -106,10 +106,10 @@ class OSMFile(object):
|
|
|
106
106
|
|
|
107
107
|
def __init__(self, nodes: dict[int, OSMNode] = None, ways: dict[int, OSMWay] = None):
|
|
108
108
|
"""
|
|
109
|
-
Represents an editable general
|
|
109
|
+
Represents an editable general-purpose OSM file.
|
|
110
110
|
|
|
111
|
-
:param nodes: nodes
|
|
112
|
-
:param ways: ways
|
|
111
|
+
:param nodes: Initial nodes to include.
|
|
112
|
+
:param ways: Initial ways to include.
|
|
113
113
|
"""
|
|
114
114
|
self.nodes: dict[int, OSMNode] = {}
|
|
115
115
|
self.ways: dict[int, OSMWay] = {}
|
|
@@ -126,11 +126,11 @@ class OSMFile(object):
|
|
|
126
126
|
|
|
127
127
|
def add_node(self, node: OSMNode) -> OSMNode:
|
|
128
128
|
"""
|
|
129
|
-
Adds the given node
|
|
129
|
+
Adds the given node.
|
|
130
130
|
|
|
131
|
-
:param node:
|
|
131
|
+
:param node: Node to add.
|
|
132
132
|
|
|
133
|
-
:return:
|
|
133
|
+
:return: Added node.
|
|
134
134
|
"""
|
|
135
135
|
self.nodes[node.node_id] = node
|
|
136
136
|
if node.node_id >= self.next_node_id:
|
|
@@ -139,22 +139,22 @@ class OSMFile(object):
|
|
|
139
139
|
|
|
140
140
|
def add_node_from_coord(self, coord: Coord, tags: dict[str, Any] = None) -> OSMNode:
|
|
141
141
|
"""
|
|
142
|
-
Adds node
|
|
142
|
+
Adds a node from the given coordinate and tags.
|
|
143
143
|
|
|
144
|
-
:param coord:
|
|
145
|
-
:param tags: tags
|
|
144
|
+
:param coord: Node coordinate.
|
|
145
|
+
:param tags: Node tags.
|
|
146
146
|
|
|
147
|
-
:return:
|
|
147
|
+
:return: Added node.
|
|
148
148
|
"""
|
|
149
149
|
return self.add_node(OSMNode(self.next_node_id, coord, OSMTags.from_any_tags(tags)))
|
|
150
150
|
|
|
151
151
|
def add_way(self, way: OSMWay) -> OSMWay:
|
|
152
152
|
"""
|
|
153
|
-
Adds the given way
|
|
153
|
+
Adds the given way.
|
|
154
154
|
|
|
155
|
-
:param way:
|
|
155
|
+
:param way: Way to add.
|
|
156
156
|
|
|
157
|
-
:return:
|
|
157
|
+
:return: Added way.
|
|
158
158
|
"""
|
|
159
159
|
self.ways[way.way_id] = way
|
|
160
160
|
if way.way_id >= self.next_way_id:
|
|
@@ -163,34 +163,34 @@ class OSMFile(object):
|
|
|
163
163
|
|
|
164
164
|
def add_way_from_coords(self, coords: list[Coord], tags: dict[str, Any] = None) -> OSMWay:
|
|
165
165
|
"""
|
|
166
|
-
Adds way
|
|
166
|
+
Adds a way from node coordinates and tags.
|
|
167
167
|
|
|
168
|
-
:param coords:
|
|
169
|
-
:param tags: tags
|
|
168
|
+
:param coords: Coordinates of the nodes on the way.
|
|
169
|
+
:param tags: Way tags.
|
|
170
170
|
|
|
171
|
-
:return:
|
|
171
|
+
:return: Added way.
|
|
172
172
|
"""
|
|
173
173
|
return self.add_way_from_nodes(coords, tags)
|
|
174
174
|
|
|
175
175
|
def add_way_from_node_ids(self, node_ids: list[int], tags: dict[str, Any] = None) -> OSMWay:
|
|
176
176
|
"""
|
|
177
|
-
Adds way
|
|
177
|
+
Adds a way from node IDs and tags.
|
|
178
178
|
|
|
179
|
-
:param node_ids:
|
|
180
|
-
:param tags: tags
|
|
179
|
+
:param node_ids: IDs of the nodes on the way.
|
|
180
|
+
:param tags: Way tags.
|
|
181
181
|
|
|
182
|
-
:return:
|
|
182
|
+
:return: Added way.
|
|
183
183
|
"""
|
|
184
184
|
return self.add_way_from_nodes(node_ids, tags)
|
|
185
185
|
|
|
186
186
|
def add_way_from_nodes(self, elements: list[OSMNode | Coord | int], tags: dict[str, Any] = None) -> OSMWay:
|
|
187
187
|
"""
|
|
188
|
-
Adds way
|
|
188
|
+
Adds a way from nodes, coordinates, or node IDs and tags.
|
|
189
189
|
|
|
190
|
-
:param elements:
|
|
191
|
-
:param tags: tags
|
|
190
|
+
:param elements: Nodes, coordinates, or node IDs that make up the way.
|
|
191
|
+
:param tags: Way tags.
|
|
192
192
|
|
|
193
|
-
:return:
|
|
193
|
+
:return: Added way.
|
|
194
194
|
"""
|
|
195
195
|
node_ids = []
|
|
196
196
|
for elem in elements:
|
|
@@ -204,9 +204,9 @@ class OSMFile(object):
|
|
|
204
204
|
|
|
205
205
|
def write(self, filename: str):
|
|
206
206
|
"""
|
|
207
|
-
Writes this OSM file
|
|
207
|
+
Writes this OSM file to the given path.
|
|
208
208
|
|
|
209
|
-
:param filename: file path
|
|
209
|
+
:param filename: Destination file path.
|
|
210
210
|
"""
|
|
211
211
|
root = lxml.etree.Element("osm")
|
|
212
212
|
root.attrib.update({
|
|
@@ -11,11 +11,11 @@ class OSMNode(object):
|
|
|
11
11
|
|
|
12
12
|
def __init__(self, node_id: int, coord: Coord, tags: OSMTags):
|
|
13
13
|
"""
|
|
14
|
-
Creates an
|
|
14
|
+
Creates an OSM node from the given ID, coordinate, and tags.
|
|
15
15
|
|
|
16
|
-
:param node_id:
|
|
17
|
-
:param coord:
|
|
18
|
-
:param tags: tags
|
|
16
|
+
:param node_id: Node ID.
|
|
17
|
+
:param coord: Node coordinate.
|
|
18
|
+
:param tags: Node tags.
|
|
19
19
|
"""
|
|
20
20
|
self.node_id = node_id
|
|
21
21
|
self.coord = coord
|
|
@@ -12,11 +12,11 @@ class OSMTags(object):
|
|
|
12
12
|
@classmethod
|
|
13
13
|
def from_any_tags(cls, any_tags: dict[str, Any] = None) -> Self:
|
|
14
14
|
"""
|
|
15
|
-
Creates an
|
|
15
|
+
Creates an OSM tag collection from values with inferred data types.
|
|
16
16
|
|
|
17
|
-
:param any_tags:
|
|
17
|
+
:param any_tags: Tags whose values may have any supported type.
|
|
18
18
|
|
|
19
|
-
:return: OSM tag
|
|
19
|
+
:return: OSM tag collection.
|
|
20
20
|
"""
|
|
21
21
|
if any_tags is None:
|
|
22
22
|
return OSMTags({})
|
|
@@ -24,9 +24,9 @@ class OSMTags(object):
|
|
|
24
24
|
|
|
25
25
|
def __init__(self, tags: dict[str, Any]):
|
|
26
26
|
"""
|
|
27
|
-
Creates an
|
|
27
|
+
Creates an OSM tag collection from string tags.
|
|
28
28
|
|
|
29
|
-
:param tags:
|
|
29
|
+
:param tags: Tags to store.
|
|
30
30
|
"""
|
|
31
31
|
self.tags = tags
|
|
32
32
|
|
|
@@ -10,11 +10,11 @@ class OSMWay(object):
|
|
|
10
10
|
|
|
11
11
|
def __init__(self, way_id: int, node_ids: list[int], tags: OSMTags):
|
|
12
12
|
"""
|
|
13
|
-
Creates an
|
|
13
|
+
Creates an OSM way from the given ID, node IDs, and tags.
|
|
14
14
|
|
|
15
|
-
:param way_id:
|
|
16
|
-
:param node_ids:
|
|
17
|
-
:param tags: tags
|
|
15
|
+
:param way_id: Way ID.
|
|
16
|
+
:param node_ids: Node IDs that make up the way.
|
|
17
|
+
:param tags: Way tags.
|
|
18
18
|
"""
|
|
19
19
|
self.way_id = way_id
|
|
20
20
|
self.node_ids = node_ids
|
|
@@ -150,10 +150,10 @@ class BagReader(AbstractContextManager, BagIOBase):
|
|
|
150
150
|
"""
|
|
151
151
|
Creates a ``BagReader`` instance to read messages from a ROS2 bag file in the specified directory.
|
|
152
152
|
|
|
153
|
-
:param db_dir:
|
|
154
|
-
:param db_filename:
|
|
155
|
-
:param kwargs:
|
|
156
|
-
:return:
|
|
153
|
+
:param db_dir: Directory containing the SQLite DB file.
|
|
154
|
+
:param db_filename: SQLite DB filename to read. Default is "bag.db".
|
|
155
|
+
:param kwargs: Additional keyword arguments to pass to the ``BagReader`` constructor.
|
|
156
|
+
:return: A ``BagReader`` instance.
|
|
157
157
|
"""
|
|
158
158
|
return BagReader(make_path(db_dir) / db_filename)
|
|
159
159
|
|
|
@@ -161,7 +161,7 @@ class BagReader(AbstractContextManager, BagIOBase):
|
|
|
161
161
|
"""
|
|
162
162
|
Creates a ``BagReader`` instance to read messages from a ROS2 bag file.
|
|
163
163
|
|
|
164
|
-
:param bag_file_path:
|
|
164
|
+
:param bag_file_path: Path to the SQLite DB file to read.
|
|
165
165
|
"""
|
|
166
166
|
super().__init__(bag_file_path)
|
|
167
167
|
|
|
@@ -204,10 +204,10 @@ class BagWriter(AbstractContextManager, BagIOBase):
|
|
|
204
204
|
"""
|
|
205
205
|
Creates a ``BagWriter`` instance to write messages to a ROS2 bag file in the specified directory.
|
|
206
206
|
|
|
207
|
-
:param db_dir:
|
|
208
|
-
:param db_filename:
|
|
209
|
-
:param kwargs:
|
|
210
|
-
:return:
|
|
207
|
+
:param db_dir: Directory where the SQLite DB file will be created.
|
|
208
|
+
:param db_filename: SQLite DB filename to create. Default is "bag.db".
|
|
209
|
+
:param kwargs: Additional keyword arguments to pass to the ``BagWriter`` constructor.
|
|
210
|
+
:return: A ``BagWriter`` instance.
|
|
211
211
|
"""
|
|
212
212
|
return BagWriter(make_path(db_dir) / db_filename, **kwargs)
|
|
213
213
|
|
|
@@ -215,13 +215,13 @@ class BagWriter(AbstractContextManager, BagIOBase):
|
|
|
215
215
|
"""
|
|
216
216
|
Creates a ``BagWriter`` instance to write messages to a ROS2 bag file.
|
|
217
217
|
|
|
218
|
-
:param bag_file_path:
|
|
219
|
-
:param overwrite:
|
|
218
|
+
:param bag_file_path: Path to the SQLite DB file to create.
|
|
219
|
+
:param overwrite: Whether to replace the SQLite DB file if it already exists. If ``False`` and the file
|
|
220
220
|
already exists, a ``FileExistsError`` is raised. If ``True``, the existing file is deleted
|
|
221
221
|
and a new one is created.
|
|
222
|
-
:param exist_ok:
|
|
223
|
-
|
|
224
|
-
|
|
222
|
+
:param exist_ok: Whether to allow an existing SQLite DB file. If ``False`` and the file already exists,
|
|
223
|
+
a ``FileExistsError`` is raised. If ``True``, the existing file is used and no new file is
|
|
224
|
+
created.
|
|
225
225
|
"""
|
|
226
226
|
super().__init__(bag_file_path)
|
|
227
227
|
|
|
@@ -57,9 +57,9 @@ class Pose(object):
|
|
|
57
57
|
@classmethod
|
|
58
58
|
def interpolate(cls, a: Self, b: Self, t: float) -> Self:
|
|
59
59
|
"""
|
|
60
|
-
Interpolates between two
|
|
60
|
+
Interpolates between two poses using ``a * t + b * (1 - t)``.
|
|
61
61
|
|
|
62
|
-
:return:
|
|
62
|
+
:return: Interpolated pose.
|
|
63
63
|
"""
|
|
64
64
|
ts = a.ts + (b.ts - a.ts) * t
|
|
65
65
|
p = a.p + (b.p - a.p) * t
|
|
@@ -68,11 +68,11 @@ class Pose(object):
|
|
|
68
68
|
|
|
69
69
|
def __init__(self, ts: float, p: np.ndarray, q: np.ndarray):
|
|
70
70
|
"""
|
|
71
|
-
Represents a pose
|
|
71
|
+
Represents a timestamped pose.
|
|
72
72
|
|
|
73
|
-
:param ts: timestamp
|
|
74
|
-
:param p:
|
|
75
|
-
:param q:
|
|
73
|
+
:param ts: Pose timestamp.
|
|
74
|
+
:param p: Position vector.
|
|
75
|
+
:param q: Orientation quaternion.
|
|
76
76
|
"""
|
|
77
77
|
self.ts = ts
|
|
78
78
|
self.p = p
|
|
@@ -80,9 +80,9 @@ class Pose(object):
|
|
|
80
80
|
|
|
81
81
|
def matrix(self) -> np.ndarray:
|
|
82
82
|
"""
|
|
83
|
-
Returns the transformation matrix
|
|
83
|
+
Returns the transformation matrix for this pose.
|
|
84
84
|
|
|
85
|
-
:return:
|
|
85
|
+
:return: Transformation matrix.
|
|
86
86
|
"""
|
|
87
87
|
r = pyquat.Quaternion(self.q).rotation_matrix
|
|
88
88
|
t = self.p[:, None]
|
|
@@ -90,21 +90,21 @@ class Pose(object):
|
|
|
90
90
|
|
|
91
91
|
def translate(self, v: np.ndarray) -> np.ndarray:
|
|
92
92
|
"""
|
|
93
|
-
|
|
93
|
+
Translates the given vector by the pose position.
|
|
94
94
|
|
|
95
|
-
:param v:
|
|
95
|
+
:param v: Vector to translate.
|
|
96
96
|
|
|
97
|
-
:return:
|
|
97
|
+
:return: Translated vector.
|
|
98
98
|
"""
|
|
99
99
|
return self.p + v
|
|
100
100
|
|
|
101
101
|
def rotate(self, v: np.ndarray) -> np.ndarray:
|
|
102
102
|
"""
|
|
103
|
-
Rotates the given vector
|
|
103
|
+
Rotates the given vector by the pose orientation.
|
|
104
104
|
|
|
105
|
-
:param v:
|
|
105
|
+
:param v: Vector to rotate.
|
|
106
106
|
|
|
107
|
-
:return:
|
|
107
|
+
:return: Rotated vector.
|
|
108
108
|
"""
|
|
109
109
|
return pyquat.Quaternion(self.q).rotate(v)
|
|
110
110
|
|
|
@@ -134,24 +134,24 @@ class Proj(ABC):
|
|
|
134
134
|
@abstractmethod
|
|
135
135
|
def from_latlon(self, lat: float, lon: float) -> tuple[float, float]:
|
|
136
136
|
"""
|
|
137
|
-
|
|
137
|
+
Projects latitude and longitude into the projection coordinate system.
|
|
138
138
|
|
|
139
|
-
:param lat:
|
|
140
|
-
:param lon:
|
|
139
|
+
:param lat: Latitude.
|
|
140
|
+
:param lon: Longitude.
|
|
141
141
|
|
|
142
|
-
:return:
|
|
142
|
+
:return: Projected ``x`` and ``y`` coordinates.
|
|
143
143
|
"""
|
|
144
144
|
pass
|
|
145
145
|
|
|
146
146
|
@abstractmethod
|
|
147
147
|
def to_latlon(self, x: float, y: float) -> tuple[float, float]:
|
|
148
148
|
"""
|
|
149
|
-
|
|
149
|
+
Converts projection coordinates back to latitude and longitude.
|
|
150
150
|
|
|
151
|
-
:param x:
|
|
152
|
-
:param y:
|
|
151
|
+
:param x: X coordinate in the projection coordinate system.
|
|
152
|
+
:param y: Y coordinate in the projection coordinate system.
|
|
153
153
|
|
|
154
|
-
:return:
|
|
154
|
+
:return: Latitude and longitude.
|
|
155
155
|
"""
|
|
156
156
|
pass
|
|
157
157
|
|
|
@@ -301,11 +301,11 @@ def default_proj() -> Proj:
|
|
|
301
301
|
|
|
302
302
|
def make_proj(spec_str: str) -> Proj | None:
|
|
303
303
|
"""
|
|
304
|
-
Constructs cartographic projection from
|
|
304
|
+
Constructs a cartographic projection from a projection spec string.
|
|
305
305
|
|
|
306
|
-
:param spec_str:
|
|
306
|
+
:param spec_str: Projection spec string.
|
|
307
307
|
|
|
308
|
-
:return: projection
|
|
308
|
+
:return: Cartographic projection, or ``None`` when no spec is provided.
|
|
309
309
|
"""
|
|
310
310
|
|
|
311
311
|
if spec_str is None:
|
|
@@ -333,27 +333,27 @@ class Coord(object):
|
|
|
333
333
|
@classmethod
|
|
334
334
|
def from_pose(cls, pose: Pose, proj: Proj | None) -> Self:
|
|
335
335
|
"""
|
|
336
|
-
Creates a
|
|
336
|
+
Creates a coordinate from a pose.
|
|
337
337
|
|
|
338
|
-
:param pose:
|
|
339
|
-
:param proj:
|
|
338
|
+
:param pose: Pose to convert.
|
|
339
|
+
:param proj: Cartographic projection to use.
|
|
340
340
|
|
|
341
|
-
:return:
|
|
341
|
+
:return: Generated coordinate.
|
|
342
342
|
"""
|
|
343
343
|
return cls.from_xy(pose.p[0], pose.p[1], pose.p[2], proj, pose.ts)
|
|
344
344
|
|
|
345
345
|
@classmethod
|
|
346
346
|
def from_latlon(cls, lat: float, lon: float, ele: float, proj: Proj | None, ts: float = 0) -> Self:
|
|
347
347
|
"""
|
|
348
|
-
Creates a
|
|
348
|
+
Creates a coordinate from latitude and longitude.
|
|
349
349
|
|
|
350
|
-
:param lat:
|
|
351
|
-
:param lon:
|
|
352
|
-
:param ele:
|
|
353
|
-
:param proj:
|
|
354
|
-
:param ts:
|
|
350
|
+
:param lat: Latitude.
|
|
351
|
+
:param lon: Longitude.
|
|
352
|
+
:param ele: Elevation.
|
|
353
|
+
:param proj: Cartographic projection to use.
|
|
354
|
+
:param ts: Timestamp.
|
|
355
355
|
|
|
356
|
-
:return:
|
|
356
|
+
:return: Generated coordinate.
|
|
357
357
|
"""
|
|
358
358
|
if proj is None:
|
|
359
359
|
return Coord(ts, lat, lon, ele, 0.0, 0.0, pdt.BaseModel())
|
|
@@ -364,15 +364,15 @@ class Coord(object):
|
|
|
364
364
|
@classmethod
|
|
365
365
|
def from_xy(cls, x: float, y: float, ele: float, proj: Proj | None, ts: float = 0) -> Self:
|
|
366
366
|
"""
|
|
367
|
-
Creates a
|
|
367
|
+
Creates a coordinate from projected coordinates.
|
|
368
368
|
|
|
369
|
-
:param x:
|
|
370
|
-
:param y:
|
|
371
|
-
:param ele:
|
|
372
|
-
:param proj:
|
|
373
|
-
:param ts:
|
|
369
|
+
:param x: X coordinate in cartographic projection.
|
|
370
|
+
:param y: Y coordinate in cartographic projection.
|
|
371
|
+
:param ele: Elevation.
|
|
372
|
+
:param proj: Cartographic projection to use.
|
|
373
|
+
:param ts: Timestamp.
|
|
374
374
|
|
|
375
|
-
:return:
|
|
375
|
+
:return: Generated coordinate.
|
|
376
376
|
"""
|
|
377
377
|
if proj is None:
|
|
378
378
|
return Coord(ts, 0.0, 0.0, ele, x, y, pdt.BaseModel())
|
|
@@ -382,15 +382,15 @@ class Coord(object):
|
|
|
382
382
|
|
|
383
383
|
def __init__(self, ts: float, lat: float, lon: float, ele: float, x: float, y: float, spec: pdt.BaseModel):
|
|
384
384
|
"""
|
|
385
|
-
Represents a coordinate
|
|
386
|
-
|
|
387
|
-
:param ts:
|
|
388
|
-
:param lat:
|
|
389
|
-
:param lon:
|
|
390
|
-
:param ele:
|
|
391
|
-
:param x:
|
|
392
|
-
:param y:
|
|
393
|
-
:param spec:
|
|
385
|
+
Represents a timestamped coordinate.
|
|
386
|
+
|
|
387
|
+
:param ts: Timestamp.
|
|
388
|
+
:param lat: Latitude.
|
|
389
|
+
:param lon: Longitude.
|
|
390
|
+
:param ele: Elevation.
|
|
391
|
+
:param x: X coordinate in the projection coordinate system.
|
|
392
|
+
:param y: Y coordinate in the projection coordinate system.
|
|
393
|
+
:param spec: Projection specification.
|
|
394
394
|
"""
|
|
395
395
|
self.ts = ts
|
|
396
396
|
self.lat = lat
|
|
@@ -40,7 +40,7 @@ def make_trivial_volume_func() -> Callable[[str], int]:
|
|
|
40
40
|
value each time the function is called with the same name. If a new name is provided,
|
|
41
41
|
a new generator is created for that name.
|
|
42
42
|
|
|
43
|
-
:return:
|
|
43
|
+
:return: Callable that takes a name (str) and returns the next integer volume.
|
|
44
44
|
"""
|
|
45
45
|
|
|
46
46
|
def trivial_volume_generator() -> Generator[int, None, None]:
|
|
@@ -67,12 +67,11 @@ def make_volume_parser(template: str) -> Callable[[str], dict[str, int]]:
|
|
|
67
67
|
The returned parser function takes a filename as input and extracts the volume values
|
|
68
68
|
as a dictionary where the keys are the placeholder names and the values are the corresponding integers.
|
|
69
69
|
|
|
70
|
-
:param template:
|
|
70
|
+
:param template: String template defining the filename structure with volume placeholders.
|
|
71
71
|
Placeholders are enclosed in double curly braces `{{}}` and can optionally include
|
|
72
72
|
a name, a prefix, and a suffix (e.g., `{name:prefix{}suffix}`).
|
|
73
73
|
|
|
74
|
-
:return:
|
|
75
|
-
placeholder names to their extracted integer values.
|
|
74
|
+
:return: Callable that takes a filename (str) and returns extracted integer values keyed by placeholder name.
|
|
76
75
|
|
|
77
76
|
:raises ValueError: if the template is invalid or cannot be parsed.
|
|
78
77
|
"""
|
|
@@ -128,13 +127,12 @@ def make_volume_generator(template: str) -> Callable[[Callable[[str], int]], tup
|
|
|
128
127
|
The returned generator function takes a volume function as input, which determines the
|
|
129
128
|
volume values for each placeholder, and produces filenames with the corresponding volumes.
|
|
130
129
|
|
|
131
|
-
:param template:
|
|
130
|
+
:param template: String template defining the filename structure with volume placeholders.
|
|
132
131
|
Placeholders are enclosed in double curly braces `{{}}` and can optionally include
|
|
133
132
|
a name, a prefix, and a suffix (e.g., `{name:prefix{}suffix}`).
|
|
134
133
|
|
|
135
|
-
:return:
|
|
136
|
-
|
|
137
|
-
placeholder names to their corresponding volume values (dict[str, int]).
|
|
134
|
+
:return: Callable generator that takes a volume function (Callable[[str], int]) and returns the generated
|
|
135
|
+
filename (str) with the volume values keyed by placeholder name (dict[str, int]).
|
|
138
136
|
|
|
139
137
|
:raises ValueError: if the template is invalid or cannot be parsed.
|
|
140
138
|
"""
|
|
@@ -181,13 +179,12 @@ def collect_volumed_filenames(template: str) -> Generator[tuple[str, dict[str, i
|
|
|
181
179
|
This function scans the folder containing the template and attempts to parse filenames
|
|
182
180
|
to extract volume values based on the template.
|
|
183
181
|
|
|
184
|
-
:param template:
|
|
182
|
+
:param template: String template defining the filename structure with volume placeholders.
|
|
185
183
|
Placeholders are enclosed in double curly braces `{{}}` and can optionally include
|
|
186
184
|
a name, a prefix, and a suffix (e.g., `{name:prefix{}suffix}`).
|
|
187
185
|
|
|
188
|
-
:return:
|
|
189
|
-
|
|
190
|
-
integer volume values.
|
|
186
|
+
:return: Generator yielding each matching filename path and its extracted integer volume values keyed by
|
|
187
|
+
placeholder name.
|
|
191
188
|
"""
|
|
192
189
|
folder = os.path.dirname(template)
|
|
193
190
|
basename = os.path.basename(template)
|
|
@@ -214,14 +211,13 @@ def populate_volumed_filenames(
|
|
|
214
211
|
This function uses a volume function to generate unique volume values for each placeholder
|
|
215
212
|
and produces filenames with the corresponding volumes.
|
|
216
213
|
|
|
217
|
-
:param template:
|
|
214
|
+
:param template: String template defining the filename structure with volume placeholders.
|
|
218
215
|
Placeholders are enclosed in double curly braces `{{}}` and can optionally include
|
|
219
216
|
a name, a prefix, and a suffix (e.g., `{name:prefix{}suffix}`).
|
|
220
|
-
:param volume_func:
|
|
221
|
-
|
|
217
|
+
:param volume_func: Callable that takes a placeholder name (str) and returns the next integer volume value.
|
|
218
|
+
If not provided, a trivial volume function is used.
|
|
222
219
|
|
|
223
|
-
:return:
|
|
224
|
-
and the second element is a dictionary mapping placeholder names to their corresponding
|
|
220
|
+
:return: Generator yielding each generated filename and its volume values keyed by placeholder name.
|
|
225
221
|
"""
|
|
226
222
|
folder = os.path.dirname(template)
|
|
227
223
|
basename = os.path.basename(template)
|