Skip to content

Commit

Permalink
Aedat compatibility with DV
Browse files Browse the repository at this point in the history
Multiple changes to ensure that generated aedat files can be loaded by DV. The biggest change is the addition of file data tables (essentially a data index at the end of aedat files), which DV requires.

Whilst loading and play back works, I've experienced minor issues when trying to load multiple files in a row (restarting DV is often required), when playing short files, or when enabling the loop playback function of DV. Some of these issues could come from the size of the packets generated by faery (typically bigger than DV's), a bug in faery.aedat, or a bug in DV. Since the latter is not completely open-source, we will need help from Inivation / Synsense to investigate further (if there is interest for better support).

Fixes #13.
  • Loading branch information
aMarcireau committed Feb 2, 2025
1 parent 85492ab commit a100197
Show file tree
Hide file tree
Showing 39 changed files with 2,829 additions and 746 deletions.
38 changes: 22 additions & 16 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,16 @@ crate-type = ["cdylib"]
name = "faery"

[dependencies]
flatbuffers = "24.3.25"
flatbuffers = "25.1.24"
fontdue = "0.9.2"
gifski = {version = "1.32.0", default-features = false}
image = {version = "0.25.1", default-features = false, features = ["png"]}
lz4 = "1.28.0"
mp4 = "0.14.0"
mustache = "0.9.0"
neuromorphic-types = "0.4.0"
numpy = {version = "0.22.0"}
pyo3 = {version = "0.22.0", features = ["extension-module"]}
numpy = {version = "0.23.0"}
pyo3 = {version = "0.23.4", features = ["extension-module"]}
resvg = "0.44.0"
roxmltree = "0.20.0"
serde = {version = "1.0", features = ["derive"]}
Expand Down
17 changes: 14 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ Faery converts neuromorphic event-based data between formats. It can also genera
- [Format and lint](#format-and-lint)
- [Test](#test)
- [Upload a new version](#upload-a-new-version)
- [Update flatbuffers definitions for AEDAT](#update-flatbuffers-definitions-for-aedat)
- [Acknowledgements](#acknowledgements)

## Using Faery from the command line
Expand All @@ -33,8 +34,8 @@ Faery converts neuromorphic event-based data between formats. It can also genera
### Examples

```sh
# Convert a Prophesee raw file (input.raw) to AEDAT (output.aedat)
faery input file input.raw output file output.aedat
# Convert a Prophesee raw file (input.raw) to AEDAT (output.aedat4)
faery input file input.raw output file output.aedat4

# Render an event file (input.es) as a real-time video (output.mp4)
faery input file input.es filter regularize 60.0 filter render exponential 0.2 starry_night output file output.mp4
Expand All @@ -49,7 +50,7 @@ faery input file input.es filter regularize 600.0 filter render exponential 0.03
faery input file input.es filter regularize 60.0 filter render exponential 0.2 starry_night output files 'frames/{index:04}.png'

# Print ON events to the terminal
faery input file input.aedat filter remove-off-events
faery input file input.aedat4 filter remove-off-events

# Read event data from UDP and write it to a CSV file (output.csv)
faery input udp 0.0.0.0:3000 output file output.csv
Expand Down Expand Up @@ -224,6 +225,16 @@ pytest tests

3. Create a new release on GitHub. GitHub actions should build wheels and push them to PyPI.

### Update flatbuffers definitions for AEDAT

After modifying any of the files in _src/aedat/flatbuffers_, re-generate the Rust interfaces.

(Last run with flatc version 25.1.24)

```sh
flatc --rust -o src/aedat/ src/aedat/flatbuffers/*.fbs
```

## Acknowledgements

Faery was initiated at the [2024 Telluride neuromorphic workshop](https://sites.google.com/view/telluride-2024/) by
Expand Down
2 changes: 1 addition & 1 deletion python/faery/cli/info.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ def run(self, arguments: list[str]):
}
if file_type == "aedat":
info["stream_compatible"] = True
with faery.aedat.Decoder(args.path) as decoder:
with faery.aedat.Decoder(path=args.path) as decoder:
info["metadata"] = {
"description": decoder.description(),
"tracks": [
Expand Down
14 changes: 7 additions & 7 deletions python/faery/file_decoder.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ def __init__(
self.event_type: typing.Optional[str] = None
if self.file_type == "aedat":
assert self.path is not None
with aedat.Decoder(self.path) as decoder:
with aedat.Decoder(path=self.path) as decoder:
found = False
for track in decoder.tracks():
if self.track_id is None:
Expand Down Expand Up @@ -225,21 +225,21 @@ def time_range(self) -> tuple[timestamp.Time, timestamp.Time]:
return time_range
else:
path_hash = None
begin: typing.Optional[int] = None
start: typing.Optional[int] = None
end: typing.Optional[int] = None
for events in self:
if len(events) > 0:
if begin is None:
begin = events["t"][0]
if start is None:
start = events["t"][0]
end = events["t"][-1]
if begin is None or end is None:
if start is None or end is None:
time_range = (
timestamp.Time(microseconds=0),
timestamp.Time(microseconds=1),
)
else:
time_range = (
timestamp.Time(microseconds=int(begin)),
timestamp.Time(microseconds=int(start)),
timestamp.Time(microseconds=(int(end) + 1)),
)
if path_hash is not None:
Expand All @@ -254,7 +254,7 @@ def time_range(self) -> tuple[timestamp.Time, timestamp.Time]:
def __iter__(self) -> collections.abc.Iterator[numpy.ndarray]:
if self.file_type == "aedat":
assert self.path is not None
with aedat.Decoder(self.path) as decoder:
with aedat.Decoder(path=self.path) as decoder:
for track, packet in decoder:
if (
track.id == self.track_id
Expand Down
48 changes: 46 additions & 2 deletions python/faery/file_encoder.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,52 @@ def events_to_file(
assert path is not None
with aedat.Encoder(
path=path if write_path is None else write_path,
description_or_tracks=[
aedat.Track(id=0, data_type="events", dimensions=dimensions),
description=[
aedat.DescriptionNode(
name="outInfo",
path="/mainloop/Recorder/outInfo/",
attributes={},
nodes=[
aedat.DescriptionNode(
name="0",
path="/mainloop/Recorder/outInfo/0/",
attributes={
"compression": aedat.DescriptionAttribute(
attribute_type="string",
value=(
"NONE"
if compression is None
else compression[0].upper()
),
),
"originalOutputName": aedat.DescriptionAttribute(
attribute_type="string", value="events"
),
"typeIdentifier": aedat.DescriptionAttribute(
attribute_type="string", value="EVTS"
),
},
nodes=[
aedat.DescriptionNode(
name="info",
path="/mainloop/Recorder/outInfo/0/info/",
attributes={
"sizeX": aedat.DescriptionAttribute(
attribute_type="int", value=dimensions[0]
),
"sizeY": aedat.DescriptionAttribute(
attribute_type="int", value=dimensions[1]
),
"source": aedat.DescriptionAttribute(
attribute_type="string", value="faery"
),
},
nodes=[],
)
],
)
],
)
],
compression=compression,
) as encoder:
Expand Down
Loading

0 comments on commit a100197

Please sign in to comment.