A sparse grid of per-voxel weights over 3-D space: Monty's
attention/voxel_grid.py::VoxelGrid.
An attention system remembers where it has looked, and it remembers it in
voxels: space is cut into cubes voxel_size on a side, and each cube that has
been looked at holds one weight. Space is mostly empty, so the grid is sparse —
Monty backs it with a pandas DataFrame whose index is the occupied voxels'
coordinates; here it is a map from a voxel to its weight, which is the same
thing with less machinery.
Which voxel a point is in
Voxels are half-open: a point on the face shared by two voxels belongs to
the one with the larger coordinate, so voxel v spans [v, v + 1) in units of
voxel_size. That is floor(point / voxel_size) and it is why a point at
exactly 0.0 is in voxel 0 while one at -0.0001 is in voxel -1.
What is not here
Monty's representation is public, so its tests can build a malformed
DataFrame and check that validate_dataframe refuses it: no (x, y, z)
index, a duplicated index, no weight column, a weight column that is not one
dimension. A map cannot be malformed in those ways — a duplicate voxel is
simply one entry — so what survives of those four cases here is the one rule a
map can break: new/3 refuses two weights for one voxel rather than letting
the last one win. from_pandas/2 and to_pandas/1 have no counterpart.
Summary
Functions
A grid with no occupied voxels.
The grid as JSON-encodable data — Monty's encode_voxel_grid.
A grid over the given voxels.
The number of occupied voxels.
Edge length of a voxel.
Each point's voxel alongside its weight — Monty's voxelize_and_bin_points.
Which voxel each point is in — Monty's voxelize_points.
The occupied voxels, in a stable order (the tuples sort).
The weights of the occupied voxels, in the same order as voxels/1.
The grid's weight at each point.
Types
Functions
A grid with no occupied voxels.
The grid as JSON-encodable data — Monty's encode_voxel_grid.
voxels and weight are parallel lists, which is how Monty writes the
MultiIndex it cannot serialise.
A grid over the given voxels.
Refuses two weights for one voxel: a voxel holds one weight, and silently keeping the last would turn a caller's bookkeeping bug into a grid that looks fine.
@spec size(t()) :: non_neg_integer()
The number of occupied voxels.
Edge length of a voxel.
Each point's voxel alongside its weight — Monty's voxelize_and_bin_points.
The rows come back in point order, which is what a caller that wants to group them by voxel needs to keep the point indices.
Which voxel each point is in — Monty's voxelize_points.
floor rather than trunc: the voxels are half-open, so the point at -0.5
is in voxel -1, not in voxel 0.
The occupied voxels, in a stable order (the tuples sort).
The weights of the occupied voxels, in the same order as voxels/1.
The grid's weight at each point.
:fill is what an unoccupied voxel answers — nil by default, the NaN of
this port, which says "no weight here" rather than "a weight of zero".