Point cloud (point_cloud)¶
Terms¶
- Point cloud
An unordered collection of spatial positions (vertices) with no connectivity information. Each vertex is independent. Per-vertex scalar or vector attributes may be stored alongside positions.
GEOM_POINT_CLOUDThe geometry type constant
"point_cloud". Stored in root.zattrsunder"geometry_type".- Per-vertex attribute
A named array, stored under
attributes/<name>/, whose length equals the number of vertices in the store. Each element corresponds to one vertex, in fragment order.
Introduction¶
The point cloud type is the simplest ZVF geometry: positions plus optional per-vertex attributes, no connectivity, no object model. It is suitable for any dataset where vertices are independent measurements — lidar scans, synchrotron absorption point data, single-molecule localisation microscopy, gene expression spatial transcriptomics, or any other spatially indexed scalar field sampled at discrete positions.
Point clouds support the full ZVF spatial indexing hierarchy (chunks, bins, fragment index) and full multi-resolution pyramids via spatial coarsening into metanodes.
Technical reference¶
Arrays present¶
Array path |
Required |
Description |
|---|---|---|
|
Yes |
Vertex positions, shape |
|
Yes |
Fragment index — |
|
No |
Per-vertex scalar or vector attributes |
No links/, object_index/, cross_chunk_links/, or object_attributes/
arrays are present. The groupings/ array is also absent; point clouds do
not have a discrete object model.
Root .zattrs required keys¶
{
"zarr_vectors_version": "1.0",
"geometry_type": "point_cloud",
"spatial_dims": 3,
"base_bin_shape": [50.0, 50.0, 50.0],
"chunk_shape": [200.0, 200.0, 200.0]
}
No type-specific metadata keys beyond the shared schema.
Write API¶
import numpy as np
from zarr_vectors.types.points import write_points
positions = np.random.default_rng(0).uniform(0, 1000, (100_000, 3)).astype(np.float32)
intensity = np.random.default_rng(1).uniform(0, 1, 100_000).astype(np.float32)
label = np.random.default_rng(2).integers(0, 8, 100_000).astype(np.int32)
write_points(
"scan.zarrvectors",
positions,
chunk_shape=(200.0, 200.0, 200.0),
bin_shape=(50.0, 50.0, 50.0),
attributes={
"intensity": intensity, # float32 scalar
"label": label, # int32 categorical
},
coordinate_system="RAS",
axis_units="micrometer",
)
Read API¶
from zarr_vectors.types.points import read_points
# Read entire store
result = read_points("scan.zarrvectors")
print(result["vertex_count"]) # int
print(result["positions"].shape) # (N, 3)
print(result["attributes"]["intensity"]) # (N,) float32
# Spatial bbox query
result = read_points(
"scan.zarrvectors",
bbox=(np.array([100., 100., 100.]), np.array([200., 200., 200.])),
)
# Coarser level
result = read_points("scan.zarrvectors", level=1)
Return dict schema¶
Key |
Type |
Description |
|---|---|---|
|
|
Total vertices in result |
|
|
Vertex positions |
|
|
Per-vertex attributes |
|
|
Resolution level read |
|
|
Effective bbox after clipping |
Attribute dtypes¶
Any numeric dtype supported by Zarr is valid for attribute arrays. Common choices:
Attribute type |
Recommended dtype |
|---|---|
Continuous scalar (intensity, FA, concentration) |
|
Integer label / class ID |
|
Boolean mask |
|
High-precision scalar (double-precision required) |
|
RGB colour |
|
Validation rules¶
L1: vertices/ and vertex_fragments/ exist at each declared level.
L2:
No
links/,object_index/, orcross_chunk_links/arrays are present.Each
attributes/<name>/array has shape consistent with the vertex count at its level.
L3:
For every non-empty chunk, the sum of range-fragment
countvalues plus explicit-fragment index counts equals the number of vertex rows in that chunk.Attribute array length matches
vertices/array length at every chunk.
Multi-resolution behaviour¶
Point cloud pyramids use pure spatial coarsening (no object thinning).
At each coarser level, vertices within each bin are replaced by a single
metanode at the bin centroid. Per-vertex attributes are aggregated using
the declared strategy (default: mean for float attributes, majority
for integer attributes).
object_sparsity is always 1.0 for point clouds and cannot be set
otherwise.