{ "cells": [ { "cell_type": "raw", "metadata": {}, "source": [ " :download:`Download the source code `." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Events Iterator using Python\n", "\n" ] }, { "cell_type": "raw", "metadata": {}, "source": [ "In the :doc:`File Loading Tutorial `, we learned how to use :class:`metavision_core.event_io.RawReader` and :class:`metavision_core.event_io.EventDatReader` to load RAW and DAT files in a flexible way.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The flexibility of these classes comes with a performance cost: events are copied in a ring buffer before being served to the user.\n", "\n" ] }, { "cell_type": "raw", "metadata": {}, "source": [ "An alternative and more efficient way to access events is to use :py:class:`metavision_core.event_io.EventsIterator`. Iterators are especially convenient for loop processing.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%matplotlib inline\n", "import os\n", "from matplotlib import pyplot as plt\n", "import numpy as np\n", "\n", "from metavision_core.event_io import EventsIterator" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Reading RAW or DAT Files with EventsIterator\n", "\n", "Let's start by getting a sample file." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "raw_path = \"spinner.raw\"\n", "# if the file doesn't exist, it will be downloaded from Prophesee's public sample server \n", "from metavision_core.utils import get_sample\n", "\n", "get_sample(raw_path, folder=\".\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# open a file\n", "mv_it = EventsIterator(raw_path, delta_t=10000, max_duration=int(1e6))\n", "print(mv_it) # show some metadata\n", "\n", "print(\"\\nImager size : \", mv_it.get_size())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We just created an iterator: to do so, we specified the `delta_t` which is the duration of the time slice we will receive at each iteration, and an optional `max_duration` which will define when to stop reading the file." ] }, { "cell_type": "raw", "metadata": {}, "source": [ "Have a look at :py:class:`metavision_core.event_io.EventsIterator` for more options." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now we can use a simple `for` loop over the iterator.\n", "\n", "```python\n", "for ev in mv_it:\n", " print(ev.size)\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Using the `EventsIterator` and `numpy`, we can write compact and efficient code. For instance, let's compute the event rate on the previous file for each millisecond (1000us):" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def ev_rate_computation_iterator():\n", " ev_rate_millisecond = np.zeros(int(1e6)//1000) # we preallocate an array for the result\n", " for ev in EventsIterator(raw_path, delta_t=10000, max_duration=int(1e6)):\n", " # np.unique allow to do an histogram quickly\n", " index, counts = np.unique(ev['t'] // 1000, return_counts=True)\n", " # for each timestamp (in millisecond) in index, we get the number of events in counts\n", " ev_rate_millisecond[index.astype(int)] = counts\n", " return ev_rate_millisecond\n", "ev_rate_millisecond = ev_rate_computation_iterator()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "plt.plot(np.arange(int(1e6)//1000)* 1000, ev_rate_millisecond)\n", "plt.title('Number of events by milliseconds as a function of time in us')\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Internally, `EventsIterator` uses a pool of buffers. So if performance and efficiency are a concern, it is a good practice to only keep the event array variable in memory as long as it is needed.\n", "The following snippet shows the best way to iterate over events and process them using a user-defined function `my_pipeline`:\n", "\n", "```python\n", "# ev is released at every iteration\n", "for ev in EventsIterator(raw_path, delta_t=10000):\n", " # your event-based pipeline using a time slice of 10000 us\n", " my_pipeline(ev)\n", "```\n", "\n", "On the contrary, the following snippet keeps all events in memory, which, while feasible in some cases, is very inefficient in terms of memory use:\n", "\n", "```python\n", "all_events = [ev for ev in EventsIterator(raw_path, delta_t=10000)]\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Creating a HAL device to initialize an EventsIterator\n", "\n", "Alternatively an EventsIterator can be constructed from a HAL device instead of passing a path or a camera serial number string. This allows a user to access or modify any facilities the device might have." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```python \n", "from metavision_core.event_io.raw_reader import initiate_device\n", "import metavision_hal\n", "device = initiate_device(path=\"\")\n", "# Access any facility on the Device, like trigger_in for example\n", "i_trigger_in = device.get_i_trigger_in()\n", "i_trigger_in.enable(metavision_hal.I_TriggerIn.Channel.MAIN)\n", "# Create EventsIterator from the Device\n", "mv_it = EventsIterator.from_device(device=device)\n", "for ev in mv_it:\n", " mv_it.reader.device\n", " pass\n", "# Note that it is not recommended to leave a device in the global scope. So either create the HAL device in a\n", "# function or delete it explicitly afterwards. Otherwise, it could result in an undefined behaviour.\n", "del device\n", "```" ] }, { "cell_type": "raw", "metadata": {}, "source": [ ".. note::\n", " This tutorial was created using `Jupiter Notebooks `_\n", "\n", " :download:`Download the source code `." ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.5" } }, "nbformat": 4, "nbformat_minor": 2 }