Skip to content

Commit

Permalink
Add a refractory period filter
Browse files Browse the repository at this point in the history
  • Loading branch information
aMarcireau committed May 27, 2023
1 parent 3cc30a5 commit b187a8f
Show file tree
Hide file tree
Showing 7 changed files with 207 additions and 192 deletions.
64 changes: 45 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,27 +35,53 @@ It supports Python 3.9, 3.10, and 3.11.

## Get started

1. Install the Python package
1. Install the Python package (system-wide or in a virtual environment)

- **Debian / Ubuntu**
```sh
sudo python3 -m pip install charidotella
```
a. System-wide installation

- **macOS**
```sh
python3 -m pip install charidotella
```
- **Debian / Ubuntu**
```sh
sudo python3 -m pip install charidotella
```

- **Windows**
- **macOS**
```sh
python3 -m pip install charidotella
```

Run in an elevated Powershell (right-click > Run as Administrator)
```powershell
& 'C:\Program Files\Python311\python.exe' -m pip install charidotella
```
- **Windows**

Run in an elevated Powershell (right-click > Run as Administrator)
```powershell
& 'C:\Program Files\Python311\python.exe' -m pip install charidotella
```

b. Installation in a virtual environment

- **Debian / Ubuntu**
```sh
python3 -m venv charidotella_venv
source charidotella_venv/bin/activate
pip install charidotella
```

- **macOS**
```sh
python3 -m venv charidotella_venv
source charidotella_venv/bin/activate
pip install charidotella
```

- **Windows**

Run in an elevated Powershell (right-click > Run as Administrator)
```powershell
& 'C:\Program Files\Python311\python.exe' -m venv charidotella_venv
charidotella_venv\Scripts\Activate.ps1
pip install charidotella
```

2. Create a directory _my-wonderful-project_ with the following structure (the file names do not matter as long as their extension is _.es_)
2. Create a directory _my-wonderful-project_ with the following structure (the file names do not matter as long as their extension is _.es_)

```txt
my-wonderful-project
Expand All @@ -66,7 +92,7 @@ It supports Python 3.9, 3.10, and 3.11.
└── file_n.es
```

3. Generate a configuration file
3. Generate a configuration file

```sh
cd my-wonderful-project
Expand All @@ -85,9 +111,9 @@ It supports Python 3.9, 3.10, and 3.11.
└── charidotella-configuration.toml
```

4. (Optional) Edit `charidotella-configuration.toml` to change the jobs' parameters
4. (Optional) Edit `charidotella-configuration.toml` to change the jobs' parameters
5. Run the jobs
5. Run the jobs
```
charidotella run
Expand All @@ -114,7 +140,7 @@ It supports Python 3.9, 3.10, and 3.11.
└── charidotella-configuration.toml
```
6. (Optional) Edit `charidotella-configuration.toml` and run `charidotella run` again (job that have already been completed will be skipped unless `--force` is used)
6. (Optional) Edit `charidotella-configuration.toml` and run `charidotella run` again (job that have already been completed will be skipped unless `--force` is used)
See `charidotella --help` for a list of other options.
Expand Down
24 changes: 22 additions & 2 deletions charidotella/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
"default": filters.default.apply,
"arbiter_saturation": filters.arbiter_saturation.apply,
"hot_pixels": filters.hot_pixels.apply,
"refractory": filters.refractory.apply,
"transpose": filters.transpose.apply,
}

Expand Down Expand Up @@ -203,7 +204,8 @@ def configuration_schema():
importlib.resources.files("charidotella").joinpath(
"assets/configuration-schema.json"
)
)
),
"r",
) as configuration_schema_file:
return json.load(configuration_schema_file)

Expand Down Expand Up @@ -412,7 +414,7 @@ def run_generators(configuration: dict[str, typing.Any]):
toml.dump(
{
"filters": {
"default": {"type": "default", "icon": "", "suffix": ""},
"default": {"type": "default", "icon": "🔆", "suffix": ""},
}
},
configuration_file,
Expand Down Expand Up @@ -448,6 +450,24 @@ def run_generators(configuration: dict[str, typing.Any]):
"ratio": "@raw(ratio)",
},
},
{
"parameters": {
"suffix": [
10**exponent for exponent in (0, 1, 2, 3, 4, 5, 6)
],
"refractory": [
utilities.timestamp_to_timecode(10**exponent)
for exponent in (0, 1, 2, 3, 4, 5, 6)
],
},
"template": {
"name": "refractory-@suffix",
"type": "refractory",
"icon": "⏳",
"suffix": "rf@suffix",
"refractory": "@refractory",
},
},
{
"parameters": {
"suffix": [
Expand Down
1 change: 1 addition & 0 deletions charidotella/filters/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from . import arbiter_saturation as arbiter_saturation
from . import default as default
from . import hot_pixels as hot_pixels
from . import refractory as refractory
from . import transpose as transpose
76 changes: 38 additions & 38 deletions charidotella/filters/hot_pixels.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,42 +31,42 @@ def apply(
else:
events = packet
numpy.add.at(count, (events["x"], events["y"]), 1)
shifted: list[numpy.ndarray] = []
for x, y in ((1, 0), (0, 1), (1, 2), (2, 1)):
kernel = numpy.zeros((3, 3))
kernel[x, y] = 1.0
shifted.append(
scipy.ndimage.convolve(
input=count,
weights=kernel,
mode="constant",
cval=0.0,
)
shifted: list[numpy.ndarray] = []
for x, y in ((1, 0), (0, 1), (1, 2), (2, 1)):
kernel = numpy.zeros((3, 3))
kernel[x, y] = 1.0
shifted.append(
scipy.ndimage.convolve(
input=count,
weights=kernel,
mode="constant",
cval=0.0,
)
ratios = numpy.divide(count, numpy.maximum.reduce(shifted) + 1.0)
mask = ratios < parameters["ratio"]
with event_stream.Decoder(input) as decoder:
with event_stream.Encoder(
output,
"dvs",
decoder.width,
decoder.height,
) as encoder:
for packet in decoder:
if packet["t"][-1] < begin:
continue
if packet["t"][0] >= end:
break
if packet["t"][0] < begin and packet["t"][-1] >= end:
events = packet[
numpy.logical_and(packet["t"] >= begin, packet["t"] < end)
]
elif begin is not None and packet["t"][0] < begin:
events = packet[packet["t"] >= begin]
elif end is not None and packet["t"][-1] >= end:
events = packet[packet["t"] < end]
else:
events = packet
events = events[mask[events["x"], events["y"]]]
if len(events) > 0:
encoder.write(events)
)
ratios = numpy.divide(count, numpy.maximum.reduce(shifted) + 1.0)
mask = ratios < parameters["ratio"]
with event_stream.Decoder(input) as decoder:
with event_stream.Encoder(
output,
"dvs",
decoder.width,
decoder.height,
) as encoder:
for packet in decoder:
if packet["t"][-1] < begin:
continue
if packet["t"][0] >= end:
break
if packet["t"][0] < begin and packet["t"][-1] >= end:
events = packet[
numpy.logical_and(packet["t"] >= begin, packet["t"] < end)
]
elif begin is not None and packet["t"][0] < begin:
events = packet[packet["t"] >= begin]
elif end is not None and packet["t"][-1] >= end:
events = packet[packet["t"] < end]
else:
events = packet
events = events[mask[events["x"], events["y"]]]
if len(events) > 0:
encoder.write(events)
46 changes: 46 additions & 0 deletions charidotella/filters/refractory.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import pathlib
import typing

import event_stream
import numpy

from .. import utilities


def apply(
input: pathlib.Path,
output: pathlib.Path,
begin: int,
end: int,
parameters: dict[str, typing.Any],
) -> None:
with event_stream.Decoder(input) as decoder:
refractory = numpy.uint64(utilities.timecode(parameters["refractory"]))
threshold_t = numpy.zeros((decoder.width, decoder.height), dtype=numpy.uint64)
with event_stream.Encoder(
output,
"dvs",
decoder.width,
decoder.height,
) as encoder:
for packet in decoder:
if packet["t"][-1] < begin:
continue
if packet["t"][0] >= end:
break
if packet["t"][0] < begin and packet["t"][-1] >= end:
events = packet[
numpy.logical_and(packet["t"] >= begin, packet["t"] < end)
]
elif begin is not None and packet["t"][0] < begin:
events = packet[packet["t"] >= begin]
elif end is not None and packet["t"][-1] >= end:
events = packet[packet["t"] < end]
else:
events = packet
mask = numpy.full(len(events), False, dtype=bool)
for index, (t, x, y, _) in enumerate(events):
if t >= threshold_t[x, y]:
mask[index] = True
threshold_t[x, y] = t + refractory
encoder.write(events[mask])
2 changes: 1 addition & 1 deletion charidotella/version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "1.1.1"
__version__ = "1.2.0"
Loading

0 comments on commit b187a8f

Please sign in to comment.