Streckenverläufe kompakt speichern und nur bei Bedarf lesen
pfaedle erzeugt für die Schweiz eine 2.6-GB-shapes.txt; die wird jetzt in shapes.bin (670 MB, mmap) umgewandelt. Halt-Positionen kommen aus shape_dist_traveled. RAM-Empfehlung im README ergänzt. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X48pE4bzjHej8w9HyZXCjb
This commit is contained in:
@@ -15,6 +15,7 @@ import shutil
|
||||
import subprocess
|
||||
import time
|
||||
import zipfile
|
||||
from array import array
|
||||
from pathlib import Path
|
||||
|
||||
import httpx
|
||||
@@ -168,6 +169,38 @@ def run_pfaedle(work: Path, rail: Path) -> Path | None:
|
||||
return out
|
||||
|
||||
|
||||
def pack_shapes(d: Path) -> None:
|
||||
"""shapes.txt ist für die Schweiz ~2.6 GB (56 Mio. Punkte) – viel zu gross für den Speicher.
|
||||
Umwandeln in shapes.bin (float32: lon, lat, Meter ab Start) + shapes.json (id -> [Start, Anzahl]),
|
||||
der Server liest daraus nur die Strecken, die er gerade braucht."""
|
||||
src = d / "shapes.txt"
|
||||
if not src.exists():
|
||||
return
|
||||
index, cur, pts, n = {}, None, [], 0
|
||||
with open(d / "shapes.bin", "wb") as out:
|
||||
def flush():
|
||||
nonlocal n
|
||||
if cur is not None:
|
||||
pts.sort()
|
||||
array("f", [v for p in pts for v in p[1:]]).tofile(out)
|
||||
index[cur] = [n, len(pts)]
|
||||
n += len(pts)
|
||||
with open(src, encoding="utf-8-sig", newline="") as f:
|
||||
r = csv.reader(f)
|
||||
h = {k: i for i, k in enumerate(next(r))}
|
||||
sid, lat, lon, seq = h["shape_id"], h["shape_pt_lat"], h["shape_pt_lon"], h["shape_pt_sequence"]
|
||||
dist = h["shape_dist_traveled"]
|
||||
for row in r:
|
||||
if row[sid] != cur:
|
||||
flush()
|
||||
assert row[sid] not in index, "shapes.txt nicht nach shape_id gruppiert"
|
||||
cur, pts = row[sid], []
|
||||
pts.append((int(row[seq]), float(row[lon]), float(row[lat]), float(row[dist])))
|
||||
flush()
|
||||
(d / "shapes.json").write_text(json.dumps(index, separators=(",", ":")))
|
||||
src.unlink()
|
||||
|
||||
|
||||
def publish(src: Path, meta: dict) -> None:
|
||||
(src / "meta.json").write_text(json.dumps(meta))
|
||||
dest = C.FEEDS_DIR / meta["feed_version"]
|
||||
@@ -212,6 +245,8 @@ def main() -> None:
|
||||
|
||||
shaped = run_pfaedle(work, work / "rail")
|
||||
meta["shapes"] = shaped is not None
|
||||
if shaped:
|
||||
pack_shapes(shaped)
|
||||
meta["source_file"] = name
|
||||
meta["prepared_at"] = int(time.time())
|
||||
publish(shaped or work / "rail", meta)
|
||||
|
||||
Reference in New Issue
Block a user