Metadata-Version: 2.4
Name: evio
Version: 0.1.0
Summary: Event-camera I/O and representations. NumPy only, no other dependencies.
Project-URL: Homepage, https://github.com/Syedmeasum14/evio
Project-URL: Issues, https://github.com/Syedmeasum14/evio/issues
Author-email: Syed Muhammad Measum Naqvi <smmnaqvi25@gmail.com>
License: MIT License
        
        Copyright (c) 2026 Syed Muhammad Measum Naqvi
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
License-File: LICENSE
Keywords: aer,computer vision,dvs,event camera,neuromorphic,spiking
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Scientific/Engineering :: Image Processing
Classifier: Typing :: Typed
Requires-Python: >=3.9
Requires-Dist: numpy>=1.21
Provides-Extra: dev
Requires-Dist: build; extra == 'dev'
Requires-Dist: pytest-cov; extra == 'dev'
Requires-Dist: pytest>=7; extra == 'dev'
Requires-Dist: ruff; extra == 'dev'
Requires-Dist: twine; extra == 'dev'
Description-Content-Type: text/markdown

# evio

**Event-camera I/O and representations. NumPy only.**

```bash
pip install evio
```

```python
import evio

events = evio.read("recording.dat")      # or .bin
events = evio.denoise(events)
tensor = evio.voxel_grid(events, bins=5)
```

Every reader returns the same structured array, so nothing downstream needs to
know which sensor or file format the events came from.

---

## Why this exists

The established package in this space is [`tonic`](https://github.com/neuromorphs/tonic),
and it does more than this one does. Two things pushed me to write `evio` anyway:

**1. `tonic` cannot coexist with NumPy 2.** It pins `numpy<2.0.0`. Installing
it into a current environment silently downgrades:

```console
$ pip install "numpy>=2" && python -c "import numpy; print(numpy.__version__)"
2.0.2
$ pip install tonic && python -c "import numpy; print(numpy.__version__)"
1.26.4
```

`evio` depends on NumPy and nothing else, and is tested against both 1.x and 2.x.

**2. `tonic` does not read Prophesee `.dat`**, which is the format N-CARS, GEN1
Automotive and the 1 Mpx detection dataset all ship in. That is most of
automotive event-vision research.

| | evio | tonic |
|---|---|---|
| Dependencies | 1 (`numpy`) | 8, including `librosa` and `scipy` |
| NumPy 2 | yes | no, pins `<2.0.0` |
| Prophesee `.dat` | yes | no |
| Bundled datasets | no | many |
| Torch integration | no | yes |

**If you want a dataset zoo and PyTorch wiring, use `tonic`.** Use `evio` when
you want to read event files into arrays quickly, in an environment you would
rather not have dictated to you.

---

## What is in it

**Formats.** N-MNIST / N-Caltech101 `.bin` and Prophesee `.dat`, read and
write, both decoded with vectorised NumPy rather than per-event loops.

**Representations.** `count_image`, `voxel_grid` (bilinear, after Zhu et al.
2019), `time_surface` (Lagorce et al. 2017), `binary_tensor` for spiking
networks, and `frames` for fixed-duration windows.

**Filters.** `denoise` (nearest-neighbour), `refractory`, `hot_pixels`,
`polarity`, `crop`.

**A CLI**, for looking at a recording without writing a script:

```console
$ evio info recording.dat
recording.dat
  events       1,048,576
  width        304
  height       240
  duration_s   0.099999
  rate_hz      10485836.5
  positive     521,114
  negative     527,462

$ evio clean noisy.dat clean.dat --denoise 5000 --refractory 1000
1,048,576 -> 793,004 events  (255,572 removed, 24.4%)
```

---

## Performance

Apple M1, Python 3.9.6, NumPy 2.0.2. Decoder figures are real recordings; the
rest is a 2 M event synthetic stream on a 640×480 sensor.

| Operation | Throughput | Notes |
|---|---:|---|
| `.bin` decode, in memory | 156 M events/s | 28,000 recordings/s |
| `.bin` read, from disk | 75 M events/s | 13,500 recordings/s |
| `.dat` read, from disk | 75 M events/s | 15,700 recordings/s |
| `time_surface` | 118 M events/s | |
| `binary_tensor` (10 bins) | 101 M events/s | |
| `hot_pixels` | 88 M events/s | |
| `voxel_grid` (5 bins) | 29 M events/s | |
| `count_image` | 21 M events/s | |
| `refractory` | 3.5 M events/s | |
| `denoise` | 0.3 M events/s | the slow one, see below |

**`denoise` is an order of magnitude slower than everything else**, and the
benchmark above is its worst case. It needs, for every event, the nearest event
in time at each of eight neighbouring pixels; that is eight binary searches
over the stream, and profiling shows those searches are essentially the whole
runtime — the sort, key arithmetic and gathers together are under 3%. Events
already known to be kept are dropped from later searches, so clustered data
(real recordings, where an edge fires several adjacent pixels at once) resolves
most events on the first offset or two, while uniformly random events do not.
Crop first if you can. A bucketed approximation would be much faster and is not
implemented, because it would change the result and this one is exact.

Reproduce with:

```bash
python benchmarks/bench.py --nmnist /path/to/NMNIST/Train --dat /path/to/ncars
```

---

## Design notes

**Events are a structured NumPy array, not a class.**

```python
EVENT_DTYPE = np.dtype([("x", "<u2"), ("y", "<u2"), ("t", "<i8"), ("p", "<i1")])
```

So they slice, sort, concatenate, `np.save`, and hand to any other library
without conversion. `x`, `y` in pixels, `t` in microseconds, `p` in `{0, 1}`.

**Polarity is normalised on read.** Sources disagree about `{0,1}` versus
`{-1,1}`; downstream code should not have to care.

**Sensor size is asked for, not assumed.** `evio.sensor_size(events)` infers it
from the data, but that is a lower bound — a recording where nothing happened
in the last column cannot tell you the column exists. Pass the real size where
you know it; the Prophesee reader can give you the one in the file header:

```python
events, meta = prophesee.read(path, with_meta=True)
size = prophesee.sensor_size_from_meta(meta)
```

**Two filters had to choose a rule, and say which.** `denoise` uses a symmetric
time window, so its result does not depend on arrival order — the classic
backwards-only formulation discards the first event of every genuine edge.
`refractory` measures from the last *kept* event, not the last event seen,
because a suppressed event never physically happened.

---

## Tests

```bash
pip install -e ".[dev]"
pytest
```

67 tests, 97% coverage. The two order-dependent filters are checked against
plain reference implementations written the slow, obvious way, because the
fast versions are not obviously equivalent to them. That caught a real bug: the
composite key packs `pixel * span + t`, and clamping only the lower end of the
time window let `t + window` overflow into the next pixel's key block, so
events were being rescued by neighbours they did not have.

---

## Status

Version 0.1.0. The API above is what I use; I would rather change it in
response to a real complaint than guess at more of it now. AEDAT and HDF5
readers are the obvious next formats.

MIT licensed.
