Skip to content

Commit 3c7f499

Browse files
committed
clean
Signed-off-by: Francis Williams <francis@fwilliams.info>
1 parent e33128d commit 3c7f499

File tree

1 file changed

+61
-35
lines changed

1 file changed

+61
-35
lines changed

fvdb/grid.py

Lines changed: 61 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -27,17 +27,12 @@
2727
"""
2828

2929
import pathlib
30-
from collections.abc import Iterator
31-
from types import ClassMethodDescriptorType
32-
from typing import TYPE_CHECKING, Any, Sequence, cast, overload
30+
from typing import TYPE_CHECKING, Any, cast, overload
3331

34-
import numpy as np
3532
import torch
3633

3734
from . import _parse_device_string
38-
from ._Cpp import ConvPackBackend
3935
from ._Cpp import GridBatch as GridBatchCpp
40-
from ._Cpp import JaggedTensor as JaggedTensorCpp
4136
from .jagged_tensor import JaggedTensor
4237
from .types import (
4338
DeviceIdentifier,
@@ -46,7 +41,6 @@
4641
resolve_device,
4742
to_Vec3f,
4843
to_Vec3fBatch,
49-
to_Vec3fBatchBroadcastable,
5044
to_Vec3fBroadcastable,
5145
to_Vec3i,
5246
to_Vec3iBroadcastable,
@@ -67,13 +61,43 @@ class Grid:
6761
6862
A :class:`Grid` does not store
6963
data itself, but rather the structure (or topology) of the sparse voxel grid. Voxel data
70-
(e.g., features, colors, densities) are stored separately as :class:`torch.Tensor` objects,
71-
which a grid can be used to index into. This allows multiple grids to share the same data
64+
(e.g., features, colors, densities) are stored separately as :class:`torch.Tensor` associated with
65+
the grid. This separation allows for flexibility in the type and number of channels of data with
66+
which a grid can be used to index into. This also allows multiple grids to share the same data
7267
storage if desired.
7368
74-
The grid is stored in a sparse format using `NanoVDB <https://github.com/AcademySoftwareFoundation/openvdb/tree/feature/nanovdb>`_
75-
where only active (non-empty) voxels are allocated, making it extremely memory efficient for representing large volumes with sparse
76-
occupancy.
69+
When using a :class:`Grid`, voxel coordinates, there are three important coordinate systems to be aware of:
70+
71+
- **World Space**: The continuous 3D coordinate system in which the grid exists.
72+
- **Voxel Space**: The discrete voxel index system, where each voxel is identified by its integer indices (i, j, k).
73+
- **Index Space**: The linear indexing of active voxels in the grid's internal storage.
74+
75+
At its core, a :class:`Grid` uses a very fast mapping from voxel space into index space to perform operations on a :class:`torch.Tensor` of
76+
data associated with the grid. This mapping allows for efficient access and manipulation of voxel data. For example:
77+
78+
.. code-block:: python
79+
80+
voxel_coords = torch.tensor([[8, 7, 6], [1, 2, 3], [4, 5, 6]], device="cuda") # Voxel space coordinates
81+
82+
# Create a Grid containing the voxels (8, 7, 6), (1, 2, 3), and (4, 5, 6) such that the voxels
83+
# have a world space size of 1x1x1, and where the [0, 0, 0] voxel in voxel space is at world space origin (0, 0, 0).
84+
grid = Grid.from_ijk(voxel_coords, voxel_size=1.0, origin=0.0, device="cuda")
85+
86+
# Create some data associated with the grid - here we have 3 voxels and 2 channels per voxel
87+
voxel_data = torch.randn(grid.num_voxels, 2, device="cuda") # Index space data
88+
89+
# Map voxel space coordinates to index space
90+
indices = grid.ijk_to_index(voxel_coords) # Shape: (3,)
91+
92+
# Access the data for the specified voxel coordinates
93+
selected_data = voxel_data[indices] # Shape: (3, 2)
94+
95+
96+
.. note::
97+
98+
The grid is stored in a sparse format using `NanoVDB <https://github.com/AcademySoftwareFoundation/openvdb/tree/feature/nanovdb>`_
99+
where only active (non-empty) voxels are allocated, making it extremely memory efficient for representing large volumes with sparse
100+
occupancy.
77101
78102
.. note::
79103
@@ -239,7 +263,7 @@ def from_ijk(
239263
ijk (torch.Tensor): Voxel coordinates to populate. A :class:`torch.Tensor` with shape ``(num_voxels, 3)`` with integer coordinates.
240264
voxel_size (NumericMaxRank1): Size of each voxel, broadcastable to shape ``(3,)``, floating dtype
241265
origin (NumericMaxRank1): Origin of the grid. *i.e.* the world-space position of the center of the ``[0,0,0]`` voxel, broadcastable to shape ``(3,)``, floating dtype
242-
device (DeviceIdentifier | None): Device to create the grid on. Defaults to None, which inherits from ``ijk``.
266+
device (DeviceIdentifier | None): Device to create the grid on. Defaults to None, which inherits the device of ``ijk``.
243267
244268
Returns:
245269
grid (Grid): A new :class:`Grid` object.
@@ -274,7 +298,7 @@ def from_mesh(
274298
mesh_faces (torch.Tensor): Faces of the mesh. A :class:`torch.Tensor` with shape ``(num_faces, 3)``.
275299
voxel_size (NumericMaxRank1): Size of each voxel, broadcastable to shape ``(3,)``, floating dtype
276300
origin (NumericMaxRank1): Origin of the grid. *i.e.* the world-space position of the center of the ``[0,0,0]`` voxel, broadcastable to shape ``(3,)``, floating dtype
277-
device (DeviceIdentifier | None): Device to create the grid on. Defaults to ``None``, which inherits from ``mesh_vertices``.
301+
device (DeviceIdentifier | None): Device to create the grid on. Defaults to ``None``, which inherits the device of ``mesh_vertices``.
278302
279303
Returns:
280304
grid (Grid): A new :class:`Grid` object with voxels covering the surface of the input mesh.
@@ -387,7 +411,7 @@ def from_nearest_voxels_to_points(
387411
points (torch.Tensor): Points to populate the grid from. A :class:`torch.Tensor` with shape ``(num_points, 3)``.
388412
voxel_size (NumericMaxRank1): Size of each voxel, broadcastable to shape ``(3,)``, floating dtype
389413
origin (NumericMaxRank1): Origin of the grid, broadcastable to shape ``(3,)``, floating dtype
390-
device (DeviceIdentifier | None): Device to create the grid on. Defaults to ``None``, which inherits from ``points``.
414+
device (DeviceIdentifier | None): Device to create the grid on. Defaults to ``None``, which inherits the device of ``points``.
391415
392416
Returns:
393417
grid (Grid): A new :class:`Grid` object.
@@ -417,7 +441,7 @@ def from_points(
417441
points (torch.Tensor): Points to populate the grid from. A :class:`torch.Tensor` with shape ``(num_points, 3)``.
418442
voxel_size (NumericMaxRank1): Size of each voxel, broadcastable to shape ``(3,)``, floating dtype
419443
origin (NumericMaxRank1): Origin of the grid, broadcastable to shape ``(3,)``, floating dtype
420-
device (DeviceIdentifier | None): Device to create the grid on. Defaults to ``None``, which inherits from ``points``.
444+
device (DeviceIdentifier | None): Device to create the grid on. Defaults to ``None``, which inherits the device of ``points``.
421445
422446
Returns:
423447
grid (Grid): A new :class:`Grid` object.
@@ -448,7 +472,7 @@ def from_zero_voxels(
448472
origin (NumericMaxRank1): Origin of the grid, broadcastable to shape ``(3,)``, floating dtype. Defaults to ``0``.
449473
450474
Returns:
451-
Grid: A new :class:`Grid` object with zero voxels.
475+
grid (Grid): A new :class:`Grid` object with zero voxels.
452476
453477
Examples:
454478
@@ -593,7 +617,7 @@ def contiguous(self) -> "Grid":
593617

594618
def conv_grid(self, kernel_size: NumericMaxRank1, stride: NumericMaxRank1 = 1) -> "Grid":
595619
"""
596-
Return a :class:`Grid` representing the active voxels at the output of a convolution applied this :class:`Grid` with a given kernel.
620+
Return a :class:`Grid` representing the active voxels at the output of a convolution applied to this :class:`Grid` with a given kernel.
597621
598622
Args:
599623
kernel_size (NumericMaxRank1): The size of the kernel to convolve with, broadcastable to shape ``(3,)``, integer dtype
@@ -815,7 +839,7 @@ def inject_from(
815839
816840
.. note::
817841
818-
The copy occurs in voxel space, the grid-to-world transform is not applied.
842+
The copy occurs in voxel space, the voxel-to-world transform is not applied.
819843
820844
.. note::
821845
@@ -1317,8 +1341,8 @@ def neighbor_indexes(self, ijk: torch.Tensor, extent: int, bitshift: int = 0) ->
13171341
def points_in_grid(self, points: torch.Tensor) -> torch.Tensor:
13181342
"""
13191343
Check if world-space points are located within active voxels. This method applies the
1320-
world-to-grid transform of this :class:`Grid` to each point, then checks if the resulting
1321-
grid coordinates correspond to active voxels.
1344+
world-to-voxel transform of this :class:`Grid` to each point, then checks if the resulting
1345+
voxel coordinates correspond to active voxels.
13221346
13231347
Args:
13241348
points (torch.Tensor): World-space points to test. A :class:`torch.Tensor` with shape ``(num_queries, 3)``.
@@ -1505,7 +1529,7 @@ def sample_bezier_with_grad(
15051529
) -> tuple[torch.Tensor, torch.Tensor]:
15061530
"""
15071531
Sample data in a :class:`torch.Tensor` associated with this :class:`Grid` at world-space
1508-
points using Bézier interpolation, and return the spatial gradients at those points.
1532+
points using Bézier interpolation, and return the sampled values and their spatial gradients at those points.
15091533
15101534
This method interpolates data at voxel centers in continuous world-space positions using cubic Bézier
15111535
interpolation. This provides smoother interpolation than trilinear but is more
@@ -1588,7 +1612,7 @@ def sample_trilinear_with_grad(
15881612
) -> tuple[torch.Tensor, torch.Tensor]:
15891613
"""
15901614
Sample data in a :class:`torch.Tensor` associated with this :class:`Grid` at world-space
1591-
points using trilinear interpolation, and return the spatial gradients at those points.
1615+
points using trilinear interpolation, and return the sampled values and their spatial gradients at those points.
15921616
15931617
This method interpolates data at voxel centers in continuous world-space positions using trilinear
15941618
interpolation.
@@ -1666,7 +1690,9 @@ def sparse_conv_halo(self, input: torch.Tensor, weight: torch.Tensor, variant: i
16661690
16671691
.. note::
16681692
1669-
Halo convolution only supports convolving when the input and output grids are the same.
1693+
Halo convolution only supports convolving when the input and output grid topology match, thus
1694+
this method does not accept an output grid. *i.e.* the output features will be associated with
1695+
this :class:`Grid`.
16701696
16711697
Args:
16721698
input (torch.Tensor): Input features for each voxel in this :class:`Grid`.
@@ -1753,7 +1779,7 @@ def refine(
17531779
17541780
.. note::
17551781
1756-
If you pass ``fine_grid = None``, this method will create a new fine grid with its
1782+
If you pass ``fine_grid = None``, this method will create a new fine :class:`Grid` with its
17571783
voxel size divided by the ``subdiv_factor`` and its origin adjusted accordingly.
17581784
17591785
.. note::
@@ -1773,7 +1799,7 @@ def refine(
17731799
subdiv_factor (NumericMaxRank1): Refinement factor between this :class:`Grid` and the fine grid, broadcastable to shape ``(3,)``, integer dtype
17741800
data (torch.Tensor): Voxel data to refine. A :class:`torch.Tensor` of shape ``(total_voxels, channels)``.
17751801
mask (torch.Tensor, optional): Boolean mask of shape ``(self.num_voxels,)``indicating which voxels in the input :class:`Grid` to refine. If ``None``, data associated with all input voxels are refined.
1776-
fine_grid (Grid, optional): Pre-allocated fine grid to use for output. If ``None``, a new grid is created.
1802+
fine_grid (Grid, optional): Pre-allocated fine :class:`Grid` to use for output. If ``None``, a new :class:`Grid` is created.
17771803
17781804
Returns:
17791805
tuple[torch.Tensor, Grid]: A tuple containing:
@@ -1797,7 +1823,7 @@ def refined_grid(
17971823
mask: torch.Tensor | None = None,
17981824
) -> "Grid":
17991825
"""
1800-
Return a refined version of the grid. *i.e* each voxel in this :class:`Grid` is subdivided
1826+
Return a refined version of this :class:`Grid`. *i.e* each voxel in this :class:`Grid` is subdivided
18011827
by the specified ``subdiv_factor`` to create a higher-resolution grid.
18021828
18031829
.. note::
@@ -1815,7 +1841,7 @@ def refined_grid(
18151841
mask (torch.Tensor, optional): Boolean mask indicating which voxels to refine. If ``None``, all voxels are refined.
18161842
18171843
Returns:
1818-
Grid: A new Grid with refined structure.
1844+
grid (Grid): A new :class:`Grid` with refined structure.
18191845
"""
18201846

18211847
subdiv_factor = to_Vec3iBroadcastable(subdiv_factor, value_constraint=ValueConstraint.POSITIVE)
@@ -1844,7 +1870,7 @@ def save_nanovdb(
18441870
name (str, optional): Optional name for the grid
18451871
compressed (bool): Whether to compress the data using Blosc compression.
18461872
Default is ``False``.
1847-
verbose (bool): Whether to print information about the saved grids.
1873+
verbose (bool): Whether to print information about the saved grid.
18481874
Default is ``False``.
18491875
"""
18501876
from ._Cpp import save as _save
@@ -1863,7 +1889,7 @@ def save_nanovdb(
18631889

18641890
def to(self, target: "str | torch.device | torch.Tensor | JaggedTensor | Grid") -> "Grid":
18651891
"""
1866-
Move grid batch to a target device or to match the device of an object (*e.g.* another :class:`Grid`, a :class:`JaggedTensor`, a :class:`torch.Tensor`, etc.).
1892+
Move this :class:`Grid` to a target device or to match the device of an object (*e.g.* another :class:`Grid`, a :class:`JaggedTensor`, a :class:`torch.Tensor`, etc.).
18671893
18681894
Args:
18691895
target (str | torch.device | torch.Tensor | JaggedTensor | Grid): Target object to determine the device.
@@ -2004,7 +2030,7 @@ def voxels_along_rays(
20042030
def world_to_grid(self, points: torch.Tensor) -> torch.Tensor:
20052031
"""
20062032
Convert world space coordinates to voxel space coordinates using the
2007-
world to grid transformation of this :class:`Grid`.
2033+
world-to-voxel transformation of this :class:`Grid`.
20082034
20092035
.. note::
20102036
@@ -2226,12 +2252,12 @@ def dual_bbox(self) -> torch.Tensor:
22262252
@property
22272253
def grid_to_world_matrix(self) -> torch.Tensor:
22282254
"""
2229-
The grid-to-world transformation matrix for this :class:`Grid`, which
2255+
The voxel-to-world transformation matrix for this :class:`Grid`, which
22302256
transforms voxel space coordinates to world space coordinates.
22312257
22322258
Returns:
22332259
grid_to_world_matrix (torch.Tensor): A ``(4, 4)``-shaped tensor representing the
2234-
grid-to-world transformation matrix.
2260+
voxel-to-world transformation matrix.
22352261
"""
22362262
return self._impl.grid_to_world_matrices[0]
22372263

@@ -2310,12 +2336,12 @@ def voxel_size(self) -> torch.Tensor:
23102336
@property
23112337
def world_to_grid_matrix(self) -> torch.Tensor:
23122338
"""
2313-
The world-to-grid transformation matrix for this :class:`Grid`, which
2339+
The world-to-voxel transformation matrix for this :class:`Grid`, which
23142340
transforms world space coordinates to voxel space coordinates.
23152341
23162342
Returns:
23172343
world_to_grid_matrix (torch.Tensor): A ``(4, 4)``-shaped tensor representing the
2318-
world-to-grid transformation matrix.
2344+
world-to-voxel transformation matrix.
23192345
"""
23202346
return self._impl.world_to_grid_matrices[0]
23212347

0 commit comments

Comments
 (0)