edge-predictor / scripts /csv_to_geffs.py
Yuvraj18's picture
Upload folder using huggingface_hub
fdae75f verified
Raw History Blame Contribute Delete
2.88 kB
from __future__ import annotations
import argparse
from pathlib import Path
import polars as pl
import tracksdata as td
from voxmodel.io import save_graph
def build_graph_from_rows(
node_rows: pl.DataFrame,
edge_rows: pl.DataFrame,
) -> td.graph.InMemoryGraph:
"""Rebuild a tracksdata graph from one dataset's node and edge rows.
tracksdata assigns fresh node ids, so CSV ``node_id``s are remapped when
adding edges (matching is spatial, not by id).
"""
graph = td.graph.InMemoryGraph()
for key in ("z", "y", "x"):
graph.add_node_attr_key(key, pl.Float64, -999999.0)
assigned = graph.bulk_add_nodes(
node_rows.select(
pl.col("t").cast(pl.Int64),
pl.col("z").cast(pl.Float64),
pl.col("y").cast(pl.Float64),
pl.col("x").cast(pl.Float64),
).to_dicts()
)
id_map = dict(zip(node_rows["node_id"].to_list(), assigned, strict=True))
if edge_rows.height:
graph.bulk_add_edges(
[
{"source_id": id_map[s], "target_id": id_map[t]}
for s, t in zip(
edge_rows["source_id"].to_list(), edge_rows["target_id"].to_list(), strict=True
)
]
)
return graph
def csv_to_geffs(
csv_path: Path | str,
out_dir: Path | str,
overwrite: bool = True,
) -> list[Path]:
"""Convert a submission CSV into one ``{dataset}.geff`` in ``out_dir``; return their paths."""
csv_path = Path(csv_path)
out_dir = Path(out_dir)
out_dir.mkdir(parents=True, exist_ok=True)
df = pl.read_csv(
csv_path,
columns=["dataset", "row_type", "node_id", "t", "z", "y", "x", "source_id", "target_id"],
)
written: list[Path] = []
for (name,), group in df.group_by("dataset"):
node_rows = group.filter(pl.col("row_type") == "node")
edge_rows = group.filter(pl.col("row_type") == "edge")
graph = build_graph_from_rows(node_rows, edge_rows)
out_path = out_dir / f"{name}.geff"
save_graph(graph, out_path, overwrite=overwrite)
written.append(out_path)
print(f"{name}: {node_rows.height} nodes, {edge_rows.height} edges -> {out_path}")
print(f"\nWrote {len(written)} geffs to {out_dir}")
return written
def main() -> None:
parser = argparse.ArgumentParser(description="Convert a submission CSV into one .geff per dataset.")
parser.add_argument("--csv", type=Path, required=True, help="Submission CSV path.")
parser.add_argument("--out-dir", type=Path, required=True, help="Output directory for .geff files.")
parser.add_argument("--no-overwrite", action="store_true", help="Do not overwrite existing geffs.")
args = parser.parse_args()
csv_to_geffs(args.csv, args.out_dir, overwrite=not args.no_overwrite)
if __name__ == "__main__":
main()