Package: expelliarmus
A Python package for decoding RAW and DAT files (Prophesee) to structured NumPy arrays of events.Supported formatsDATEVT2EVT3InstallationYou can install the library throughpip:pipinstallexpelliarmusThanks to @Tobias-Fischer, the package is also available onconda-forge!The package is tested on Windows, MacOS and Linux. Join us onDiscordto propose features or to signal bugs!DocumentationCheck outreadthedocs!Getting startedexpelliarmusis a library that allows to decode binary files generated byPropheseecameras toNumPy structured arrays.TheexpelliarmusAPI contains a single class calledWizard, that contains many methods to read a file all at once, in chunks ofchunk_sizeevents or in time windows oftime_windowmilliseconds. There are also additional methods to save structured NumPy arrays to different Prophesee encoding formats.Read a fileLet us downloadthis filefrom the Prophesee website.frompathlibimportPathimportrequestsprophesee_url="https://dataset.prophesee.ai/index.php/s/fB7xvMpE136yakl/download"fpath=Path("./pedestrians.raw")# Downloading the file if it is not available.ifnotfpath.is_file():print("Downloading the file...",end=" ")open(fpath,'wb').write(requests.get(prophesee_url).content)print("done!")else:print("File already available.")Downloading the file... done!The file that we downloaded is an EVT3 one; hence, we need to create aWizardobject choosing an"evt3"encoding.fromexpelliarmusimportWizardwizard=Wizard(encoding="evt3")The file to be read can be specified in three ways:passing thefpathargument to theWizardconstructor at object creation time.using theset_file()method.passing the file path to theread()method.Let us use the second way.wizard.set_file(fpath)Now we can use theread()method to read the binary file to a NumPy structured array.arr=wizard.read()print(f"First event encoded as (t, x, y, p):{arr[0]}")print(f"Number of events:{len(arr)}.")print(f"Recording duration:{(arr[-1]['t']-arr[0]['t'])//int(1e6)}s.")First event encoded as (t, x, y, p): (5840504, 707, 297, 0)
Number of events: 39297796.
Recording duration: 60 s.Reading in chunksThe file could be too large to be read all at once in an array; for this reason,expelliarmusprovides two generator methods:read_chunk()andread_time_window(), to read a file in chunks of achunk_sizeevents or in time windows oftime_windowmilliseconds, respectively. Let us start from the first method.chunk_size=8192wizard.set_chunk_size(chunk_size)# Calling the generator once:chunk=next(wizard.read_chunk())print(f"Chunk length:{len(chunk)}.")print(f"Chunk duration:{(chunk[-1]['t']-chunk[0]['t'])/1e3:.2f}ms.")print(f"Chunk first event:{chunk[0]}.")Chunk length: 8192.
Chunk duration: 154.27 ms.
Chunk first event: (5840504, 707, 297, 0).Let us read a chunk of at mosttime_windowmilliseconds duration from the file:time_window=5wizard.set_time_window(time_window)# Calling the generator once.chunk=next(wizard.read_time_window())print(f"Chunk length:{len(chunk)}.")print(f"Chunk duration:{(chunk[-1]['t']-chunk[0]['t'])/(1e3):.2f}ms.")print(f"Chunk first event:{chunk[0]}.")Chunk length: 47.
Chunk duration: 4.50 ms.
Chunk first event: (5840504, 707, 297, 0).Conversion among file formatsSuppose that you have a really large file encoded in DAT, likethis one. You might want to convert it to EVT2 to save disk space and have better read performance.expelliarmusallows you to do that. Let us download the file first.prophesee_url="https://dataset.prophesee.ai/index.php/s/YAri3vpPZHhEZfc/download"fpath=Path("./spinner.dat")# Downloading the file if it is not available.ifnotfpath.is_file():print("Downloading the file...",end=" ")open(fpath,'wb').write(requests.get(prophesee_url).content)print("done!")else:print("File already available.")Downloading the file... done!First we changewizardencoding and, then, we read the DAT file to an array.wizard.set_encoding("dat")arr=wizard.read(fpath)print(f"First event encoded as (t, x, y, p):{arr[0]}")print(f"Number of events:{len(arr)}.")print(f"Recording duration:{(arr[-1]['t']-arr[0]['t'])/1e6:.2f}s.")First event encoded as (t, x, y, p): (0, 237, 121, 1)
Number of events: 54165303.
Recording duration: 5.00 s.Now we define a secondWizardobject with EVT2 encoding and we use itssave()method to convert the file from DAT to EVT2.importnumpyasnpwizard_evt2=Wizard(encoding="evt2")new_fpath=Path("./spinner_evt2.raw")wizard_evt2.save(fpath=new_fpath,arr=arr)Let us check that the files are consistent.new_arr=wizard_evt2.read(new_fpath)print(f"Durations: DAT ={(arr[-1]['t']-arr[0]['t'])/1e6:.2f}s,\EVT2 ={(new_arr[-1]['t']-new_arr[0]['t'])/1e6:.2f}s.")are_equal=Trueforcoordin('t','x','y','p'):are_equal=are_equalandnp.equal(arr[coord],new_arr[coord]).all()print(f"The two arrays are{'not'if(notare_equal)else''}identical.")Durations: DAT = 5.00 s, EVT2 = 5.00 s.
The two arrays are identical.There are other methods available in the API.Check it out!A small benchmarkHere it is a small benchmark usingexpelliarmuson the file formats supported. Benchmarking is run onthis file, converted from EVT3 to DAT and EVT2 using thesave()method. The data shows the file size, read time for the full file and read time for reading the file in chunks and time windows. The performance is compared against HDF5, HDF5 LZF, HDF5 GZIP and NumPy.Full file read
------------------------------------------------------------------------------------------------------------
Software  | Size [MB] | Diff. DAT | Diff. EVT2 | Diff. EVT3 | Time [s] | Diff. DAT | Diff. EVT2 | Diff. EVT3
------------------------------------------------------------------------------------------------------------
exp. DAT  | 851       | -0%       | +100%      | +143%      | 1.15    | -0%       | +43%       | -41%       
------------------------------------------------------------------------------------------------------------
exp. EVT2 | 426       | -50%      | -0%        | +22%       | 0.80    | -30%      | -0%        | -59%       
------------------------------------------------------------------------------------------------------------
exp. EVT3 | 350       | -59%      | -18%       | -0%        | 1.95    | +70%      | +144%      | -0%        
------------------------------------------------------------------------------------------------------------
hdf5      | 1701      | +100%     | +299%      | +386%      | 0.73    | -36%      | -8%        | -62%       
------------------------------------------------------------------------------------------------------------
hdf5_lzf  | 746       | -12%      | +75%       | +113%      | 3.09    | +170%     | +287%      | +58%       
------------------------------------------------------------------------------------------------------------
hdf5_gzip | 419       | -51%      | -2%        | +20%       | 5.60    | +389%     | +600%      | +187%      
------------------------------------------------------------------------------------------------------------
numpy     | 1701      | +100%     | +299%      | +386%      | 0.32    | -72%      | -60%       | -84%       
------------------------------------------------------------------------------------------------------------Time windowing read
------------------------------------------------------------------------------------------------------------
Software  | Size [MB] | Diff. DAT | Diff. EVT2 | Diff. EVT3 | Time [s] | Diff. DAT | Diff. EVT2 | Diff. EVT3
------------------------------------------------------------------------------------------------------------
exp. DAT  | 851       | -0%       | +100%      | +143%      | 1.58    | -0%       | +4%        | -39%       
------------------------------------------------------------------------------------------------------------
exp. EVT2 | 426       | -50%      | -0%        | +22%       | 1.51    | -4%       | -0%        | -42%       
------------------------------------------------------------------------------------------------------------
exp. EVT3 | 350       | -59%      | -18%       | -0%        | 2.58    | +64%      | +71%       | -0%        
------------------------------------------------------------------------------------------------------------
hdf5      | 1701      | +100%     | +299%      | +386%      | 1.02    | -35%      | -32%       | -60%       
------------------------------------------------------------------------------------------------------------
hdf5_lzf  | 746       | -12%      | +75%       | +113%      | 3.82    | +143%     | +153%      | +48%       
------------------------------------------------------------------------------------------------------------
hdf5_gzip | 419       | -51%      | -2%        | +20%       | 6.88    | +337%     | +355%      | +166%      
------------------------------------------------------------------------------------------------------------Chunk read
------------------------------------------------------------------------------------------------------------
Software  | Size [MB] | Diff. DAT | Diff. EVT2 | Diff. EVT3 | Time [s] | Diff. DAT | Diff. EVT2 | Diff. EVT3
------------------------------------------------------------------------------------------------------------
exp. DAT  | 851       | -0%       | +100%      | +143%      | 1.64    | -0%       | +3%        | -22%       
------------------------------------------------------------------------------------------------------------
exp. EVT2 | 426       | -50%      | -0%        | +22%       | 1.58    | -3%       | -0%        | -24%       
------------------------------------------------------------------------------------------------------------
exp. EVT3 | 350       | -59%      | -18%       | -0%        | 2.09    | +28%      | +32%       | -0%        
------------------------------------------------------------------------------------------------------------
hdf5      | 1701      | +100%     | +299%      | +386%      | 4.20    | +157%     | +166%      | +101%      
------------------------------------------------------------------------------------------------------------
hdf5_lzf  | 746       | -12%      | +75%       | +113%      | 10.36   | +534%     | +555%      | +395%      
------------------------------------------------------------------------------------------------------------
hdf5_gzip | 419       | -51%      | -2%        | +20%       | 17.23   | +954%     | +989%      | +724%      
------------------------------------------------------------------------------------------------------------ContributingPlease check ourdocumentation pagefor more details on contributing.AboutThis project has been created byFabrizio OttatiandGregor Lenz.