Skip to content

Commit ffd14dc

Browse files
authored
feat: video/path dataframe cross-reference (#33)
- add VideoDataFrameBuilder - update PathDataFrameBuilder - update yaak dataset template
1 parent 2f8e584 commit ffd14dc

File tree

9 files changed

+122
-43
lines changed

9 files changed

+122
-43
lines changed

.pre-commit-config.yaml

+3-3
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,19 @@ repos:
66
- id: validate-pyproject
77

88
- repo: https://github.com/asottile/pyupgrade
9-
rev: v3.19.0
9+
rev: v3.19.1
1010
hooks:
1111
- id: pyupgrade
1212

1313
- repo: https://github.com/astral-sh/ruff-pre-commit
14-
rev: v0.8.1
14+
rev: v0.9.2
1515
hooks:
1616
- id: ruff
1717
args: [--fix]
1818
- id: ruff-format
1919

2020
- repo: https://github.com/DetachHead/basedpyright-pre-commit-mirror
21-
rev: 1.22.0
21+
rev: 1.24.0
2222
hooks:
2323
- id: basedpyright
2424

config/_templates/dataset/yaak.yaml

+54-16
Original file line numberDiff line numberDiff line change
@@ -35,17 +35,14 @@ inputs:
3535
cache_dir: /tmp/rbyte-cache
3636
functions:
3737
- _target_: pipefunc.PipeFunc
38-
scope: yaak_metadata
39-
output_name: output
40-
cache: true
4138
func:
4239
_target_: hydra.utils.get_method
4340
path: rbyte.io.build_yaak_metadata_dataframe
41+
output_name: output
42+
scope: metadata
43+
cache: true
4444

4545
- _target_: pipefunc.PipeFunc
46-
bound:
47-
path: ${data_dir}/(@=input_id@)/ai.mcap
48-
output_name: mcap
4946
func:
5047
_target_: rbyte.io.McapDataFrameBuilder
5148
decoder_factories: [rbyte.utils._mcap.ProtobufDecoderFactory]
@@ -58,18 +55,21 @@ inputs:
5855
score:
5956
_target_: polars.Float32
6057

58+
output_name: output
59+
bound:
60+
path: ${data_dir}/(@=input_id@)/ai.mcap
61+
scope: mcap
62+
6163
- _target_: pipefunc.PipeFunc
6264
func:
6365
_target_: pipefunc.helpers.collect_kwargs
6466
parameters: [meta, mcap]
65-
renames:
66-
meta: yaak_metadata.output
6767
output_name: data
68+
renames:
69+
meta: metadata.output
70+
mcap: mcap.output
6871

6972
- _target_: pipefunc.PipeFunc
70-
renames:
71-
input: data
72-
output_name: data_aligned
7373
func:
7474
_target_: rbyte.io.DataFrameAligner
7575
separator: /
@@ -111,18 +111,56 @@ inputs:
111111
tolerance: 500ms
112112
strategy: nearest
113113

114-
- _target_: pipefunc.PipeFunc
114+
output_name: data_aligned
115115
renames:
116-
input: data_aligned
117-
output_name: data_filtered
116+
input: data
117+
118+
- _target_: pipefunc.PipeFunc
118119
func:
119120
_target_: rbyte.io.DataFrameFilter
120121
predicate: |
121122
`meta/VehicleMotion/speed` > 44
123+
output_name: data_filtered
124+
renames:
125+
input: data_aligned
126+
127+
#@ for i, camera in enumerate(cameras):
128+
- _target_: pipefunc.PipeFunc
129+
func:
130+
_target_: rbyte.io.VideoDataFrameBuilder
131+
fields:
132+
frame_idx:
133+
_target_: polars.Int32
134+
135+
output_name: data_(@=camera@)
136+
bound:
137+
path: "${data_dir}/(@=input_id@)/(@=camera@).pii.mp4"
138+
139+
- _target_: pipefunc.PipeFunc
140+
func:
141+
_target_: hydra.utils.get_method
142+
path: polars.DataFrame.join
143+
#@ if i == len(cameras) - 1:
144+
output_name: data_joined
145+
#@ else:
146+
output_name: data_joined_(@=camera@)
147+
#@ end
148+
renames:
149+
#@ if i == 0:
150+
self: data_filtered
151+
#@ else:
152+
self: data_joined_(@=cameras[i-1]@)
153+
#@ end
154+
other: data_(@=camera@)
155+
bound:
156+
how: semi
157+
left_on: meta/ImageMetadata.(@=camera@)/frame_idx
158+
right_on: frame_idx
159+
#@ end
122160

123161
- _target_: pipefunc.PipeFunc
124162
renames:
125-
input: data_filtered
163+
input: data_joined
126164
output_name: samples
127165
func:
128166
_target_: rbyte.FixedWindowSampleBuilder
@@ -132,7 +170,7 @@ inputs:
132170
length: 6
133171

134172
kwargs:
135-
yaak_metadata:
173+
metadata:
136174
path: ${data_dir}/(@=input_id@)/metadata.log
137175
fields:
138176
rbyte.io.yaak.proto.sensor_pb2.ImageMetadata:

justfile

+10-10
Original file line numberDiff line numberDiff line change
@@ -62,24 +62,24 @@ visualize *ARGS: generate-config
6262
{{ ARGS }}
6363

6464
[group('visualize')]
65-
visualize-mimicgen:
66-
just visualize dataset=mimicgen logger=rerun/mimicgen ++data_dir={{ justfile_directory() }}/tests/data/mimicgen
65+
visualize-mimicgen *ARGS:
66+
just visualize dataset=mimicgen logger=rerun/mimicgen ++data_dir={{ justfile_directory() }}/tests/data/mimicgen {{ ARGS }}
6767

6868
[group('visualize')]
69-
visualize-yaak:
70-
just visualize dataset=yaak logger=rerun/yaak ++data_dir={{ justfile_directory() }}/tests/data/yaak
69+
visualize-yaak *ARGS:
70+
just visualize dataset=yaak logger=rerun/yaak ++data_dir={{ justfile_directory() }}/tests/data/yaak {{ ARGS }}
7171

7272
[group('visualize')]
73-
visualize-zod:
74-
just visualize dataset=zod logger=rerun/zod ++data_dir={{ justfile_directory() }}/tests/data/zod
73+
visualize-zod *ARGS:
74+
just visualize dataset=zod logger=rerun/zod ++data_dir={{ justfile_directory() }}/tests/data/zod {{ ARGS }}
7575

7676
[group('visualize')]
77-
visualize-nuscenes-mcap:
78-
just visualize dataset=nuscenes/mcap logger=rerun/nuscenes/mcap ++data_dir={{ justfile_directory() }}/tests/data/nuscenes/mcap
77+
visualize-nuscenes-mcap *ARGS:
78+
just visualize dataset=nuscenes/mcap logger=rerun/nuscenes/mcap ++data_dir={{ justfile_directory() }}/tests/data/nuscenes/mcap {{ ARGS }}
7979

8080
[group('visualize')]
81-
visualize-nuscenes-rrd:
82-
just visualize dataset=nuscenes/rrd logger=rerun/nuscenes/rrd ++data_dir={{ justfile_directory() }}/tests/data/nuscenes/rrd
81+
visualize-nuscenes-rrd *ARGS:
82+
just visualize dataset=nuscenes/rrd logger=rerun/nuscenes/rrd ++data_dir={{ justfile_directory() }}/tests/data/nuscenes/rrd {{ ARGS }}
8383

8484
# rerun server and viewer
8585
rerun bind="0.0.0.0" port="9876" ws-server-port="9877" web-viewer-port="9090":

pyproject.toml

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "rbyte"
3-
version = "0.10.2"
3+
version = "0.11.0"
44
description = "Multimodal PyTorch dataset library"
55
authors = [{ name = "Evgenii Gorchakov", email = "[email protected]" }]
66
maintainers = [{ name = "Evgenii Gorchakov", email = "[email protected]" }]
@@ -18,7 +18,7 @@ dependencies = [
1818
"parse>=1.20.2",
1919
"structlog>=24.4.0",
2020
"tqdm>=4.66.5",
21-
"pipefunc>=0.46.0",
21+
"pipefunc>=0.50.0",
2222
]
2323
readme = "README.md"
2424
requires-python = ">=3.12,<3.13"
@@ -49,7 +49,7 @@ yaak = ["protobuf", "ptars>=0.0.3"]
4949
jpeg = ["simplejpeg>=1.7.6"]
5050
video = [
5151
"python-vali>=4.2.0.post0; sys_platform == 'linux'",
52-
"video-reader-rs>=0.2.1",
52+
"video-reader-rs>=0.2.2",
5353
]
5454
hdf5 = ["h5py>=3.12.1"]
5555
rrd = ["rerun-sdk>=0.21.0", "pyarrow-stubs"]

src/rbyte/io/__init__.py

+7
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,13 @@
4949
else:
5050
__all__ += ["FfmpegFrameSource"]
5151

52+
try:
53+
from .video.dataframe_builder import VideoDataFrameBuilder
54+
except ImportError:
55+
pass
56+
else:
57+
__all__ += ["VideoDataFrameBuilder"]
58+
5259
try:
5360
from .yaak import YaakMetadataDataFrameBuilder, build_yaak_metadata_dataframe
5461
except ImportError:

src/rbyte/io/path/dataframe_builder.py

+7-6
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,11 @@ def __call__(self, path: PathLike[str]) -> pl.DataFrame:
4242
)
4343
raise RuntimeError(msg)
4444

45-
parent = Path(os.path.commonpath([path, parser._expression])) # pyright: ignore[reportPrivateUsage] # noqa: SLF001
46-
results = (parser.parse(p.as_posix()) for p in parent.rglob("*") if p.is_file()) # pyright: ignore[reportUnknownMemberType]
47-
48-
return pl.DataFrame(
49-
data=(r.named for r in results if isinstance(r, parse.Result)), # pyright: ignore[reportUnknownMemberType]
50-
schema=self._fields,
45+
parent = Path(
46+
os.path.commonpath([path, parser._expression.replace("\\.", ".")]) # pyright: ignore[reportPrivateUsage] # noqa: SLF001
5147
)
48+
paths = map(Path.as_posix, parent.rglob("*"))
49+
parsed = map(parser.parse, paths) # pyright: ignore[reportUnknownArgumentType, reportUnknownMemberType]
50+
data = (x.named for x in parsed if isinstance(x, parse.Result)) # pyright: ignore[reportUnknownVariableType, reportUnknownMemberType]
51+
52+
return pl.DataFrame(data=data, schema=self._fields)
+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
from collections.abc import Mapping
2+
from os import PathLike
3+
from pathlib import Path
4+
from typing import Literal, final
5+
6+
import polars as pl
7+
from polars._typing import PolarsIntegerType # noqa: PLC2701
8+
from polars.datatypes import (
9+
IntegerType, # pyright: ignore[reportUnusedImport] # noqa: F401
10+
)
11+
from pydantic import ConfigDict, validate_call
12+
from video_reader import (
13+
PyVideoReader, # pyright: ignore[reportAttributeAccessIssue, reportUnknownVariableType]
14+
)
15+
16+
type Fields = Mapping[Literal["frame_idx"], PolarsIntegerType]
17+
18+
19+
@final
20+
class VideoDataFrameBuilder:
21+
__name__ = __qualname__
22+
23+
@validate_call(config=ConfigDict(arbitrary_types_allowed=True))
24+
def __init__(self, fields: Fields) -> None:
25+
self._fields = fields
26+
27+
def __call__(self, path: PathLike[str]) -> pl.DataFrame:
28+
vr = PyVideoReader(Path(path).resolve().as_posix()) # pyright: ignore[reportUnknownVariableType]
29+
info = vr.get_info() # pyright: ignore[reportUnknownMemberType, reportUnknownVariableType]
30+
frame_count = int(info["frame_count"]) # pyright: ignore[reportUnknownArgumentType]
31+
data = pl.arange(frame_count, eager=True)
32+
33+
return pl.DataFrame(data=data, schema=self._fields) # pyright: ignore[reportArgumentType]

src/rbyte/io/yaak/idl-repo

src/rbyte/utils/tensor.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@ def pad_dim(
1414
mode: str = "constant",
1515
value: float | None = None,
1616
) -> Tensor:
17-
_pad = [(0, 0) for _ in input.shape]
18-
_pad[dim] = pad
19-
_pad = list(mit.flatten(reversed(_pad)))
17+
pad_ = [(0, 0) for _ in input.shape]
18+
pad_[dim] = pad
19+
pad_ = list(mit.flatten(reversed(pad_)))
2020

21-
return F.pad(input, _pad, mode=mode, value=value)
21+
return F.pad(input, pad_, mode=mode, value=value)
2222

2323

2424
def pad_sequence(sequences: Sequence[Tensor], dim: int, value: float = 0.0) -> Tensor:

0 commit comments

Comments
 (0)