"""Miscellaneous utilites."""
import os.path
from pathlib import Path
from typing import Optional, List
from ouster.sdk.core import SensorInfo
data_must_be_a_file_err = "The source parameter must be a path to a file."
meta_must_be_a_file_err = "The metadata parameter must be a path to a file."
def _check_sensor_metadata_for_duplicates(data_path, metas):
"""Check sensor metadata if multiple metadata files are found for the same data path in dir
Args:
data_path: data filepath found in the directory
metas: metadata filepaths found in the directory
Returns:
serial number if the metadata files are duplicates else None
"""
serial_numbers = set()
for meta in metas:
# Open each file, read its content, and create a SensorInfo object
with open(meta) as file:
meta_content = file.read()
si = SensorInfo(meta_content)
if si.sn in serial_numbers:
s = ["The following metadata files identified for "
f"{data_path} contain configuration for the same sensor {si.sn}. Files: "
f"{', '.join(sorted((set(metas))))} ",
"To resolve this, remove the extra metadata file(s) or specify the metadata "
"files manually using the --meta option."]
raise RuntimeError("\n".join(s))
serial_numbers.add(si.sn)
def _resolve_metadata_multi_with_prefix_guess(data_path: str) -> List[str]:
"""Look for best-matching metadata files from all json files in the same dir
Args:
data_path: filename location with the data, usually .pcap or .bag
Returns:
list of metadata json paths guessed with the most common prefix match
"""
if not os.path.isfile(data_path):
raise ValueError(data_must_be_a_file_err)
dirname, pcap_ = os.path.split(data_path)
if not dirname:
dirname = os.getcwd()
# find all .json files in same dir
options = list(filter(
lambda f: (Path(dirname) / f).is_file() and
f.lower().endswith(".json"), os.listdir(dirname)
))
# for each json name, find how many characters are in common
option_scores = map(lambda f: len(os.path.commonprefix([f, pcap_])),
options)
if not options:
return []
# select all jsons with the longest common prefix of equal size
sorted_options = sorted(zip(options, option_scores),
key=lambda i: i[1],
reverse=True)
best_score = sorted_options[0][1]
if not best_score:
# TWS 20240329: previously, this method would return
# any old JSON file even if there was no common prefix.
# In my experience, it's almost always an incorrect guess.
# Now it requires at least a single character to be common.
return []
else:
metas = [
os.path.join(dirname, b_path) for b_path, _ in filter(
lambda i: i[1] == best_score, sorted_options)
]
if len(metas) > 1:
_check_sensor_metadata_for_duplicates(data_path, metas)
return metas