synthbold.geometries

Definitions of raw geometry labels (e.g., Shapes, Cylinders, Cubes, etc.) that are used as inputs for data synthesis.

class synthbold.geometries.Cubes(shape: tuple[int, int, int] = (128, 128, 128), fov: tuple[float, float, float] = (1.0, 1.0, 1.0), num_objects: int | None = None, vf_range: tuple[float, float] | None = (0.05, 0.1), diameter_range: tuple[float, float] = (0.05, 2.0), allow_overlap: bool = True, device: str = 'cpu', seed: int | None = None)

Bases: ObjectGeometry

Random cube mask generator.

Generates random cube label masks with set volume fraction. Each cube is a regular cube placed at a random position in the volume with a random orientation and a random circumradius drawn uniformly from diameter_range. Follows the same interface as Cylinders; see that class for a full description of the shared parameters.

Notes

The diameter_range is interpreted as the circumdiameter (diameter of the circumscribed sphere), consistent with the Tetrahedra convention.

Examples

Create 100 random cube label maps and save to disk:

>>> shape = (128, 128, 128)
>>> fov = (32.0, 32.0, 32.0)
>>> num_cubes = 10
>>> fname = "<fname-zarr>"
>>> cube_map = Cubes(shape, fov, num_cubes)
>>> cube_map(100, fname)
classmethod from_config(config: Config) Self

Constructs cube label map instance from configuration object.

class synthbold.geometries.CylinderTrees(shape: tuple[int, int, int] = (128, 128, 128), fov: tuple[float, float, float] = (1.0, 1.0, 1.0), num_objects: int | None = None, vf_range: tuple[float, float] | None = (0.05, 0.1), diameter_range: tuple[float, float] = (0.05, 2.0), allow_overlap: bool = True, segment_length_range: tuple[float, float] = (2.0, 6.0), branch_prob: float = 0.35, branch_angle_range: tuple[float, float] = (0.2618, 0.7854), max_depth: int = 6, min_radius_fraction: float = 0.15, device: str = 'cpu', seed: int | None = None)

Bases: ObjectGeometry

Random bifurcating cylinder tree mask generator.

Generates masks of randomly branching cylinder trees, each built from straight cylindrical segments connected end-to-end. Starting from a root segment with a random position, direction, and radius (drawn the same way as Cylinders), each segment is extended by a random length and, with probability branch_prob, splits into two child segments instead of terminating. Child directions diverge from the parent by an angle drawn from branch_angle_range around a random azimuth, and child radii are derived from the parent radius via Murray’s law (r_parent^3 = r_child1^3 + r_child2^3) with a random asymmetric split, so calibre tapers realistically towards the leaves. A branch stops growing once its radius falls below min_radius_fraction of the root radius or max_depth generations have been reached. All segments belonging to one tree are written as a single object label.

Follows the same interface as Cylinders for volume-fraction/num_objects control and root diameter sampling; see that class for a full description of the shared parameters.

Parameters:
  • segment_length_range – Range of individual segment lengths in mm.

  • branch_prob – Probability that a segment bifurcates into two children instead of terminating (subject to max_depth).

  • branch_angle_range – Range of angles in radians between a parent segment and each of its two children at a bifurcation.

  • max_depth – Maximum number of branching generations grown below the root.

  • min_radius_fraction – Fraction of the root radius below which a branch stops growing.

Raises:

ValueError – If branch_prob is not in [0, 1], if max_depth is negative, or if min_radius_fraction is not in (0, 1].

Examples

Create 100 random cylinder tree label maps and save to disk:

>>> shape = (128, 128, 128)
>>> fov = (32.0, 32.0, 32.0)
>>> num_trees = 5
>>> fname = "<fname-zarr>"
>>> tree_map = CylinderTrees(shape, fov, num_trees)
>>> tree_map(100, fname)
property attrs: dict[str, Any]

Metadata for ZARR/NIfTI storage.

classmethod from_config(config: Config) Self

Constructs cylinder tree label map instance from configuration object.

class synthbold.geometries.Cylinders(shape: tuple[int, int, int] = (128, 128, 128), fov: tuple[float, float, float] = (1.0, 1.0, 1.0), num_objects: int | None = None, vf_range: tuple[float, float] | None = (0.05, 0.1), diameter_range: tuple[float, float] = (0.05, 2.0), allow_overlap: bool = True, device: str = 'cpu', seed: int | None = None)

Bases: ObjectGeometry

Random cylinder mask generator.

Generates random cylindrical label masks with set volume fraction. Volume fraction and diameters are randomly chosen from a uniform distribution with set boundaries. Optionally, instead of using volume fraction, the number of cylinders can be set directly.

These masks can be used to define random vessel distributions with set blood volume fraction and vessel diameters.

Parameters:
  • shape – Matrix size of the cylinder label map (X, Y, Z).

  • fov – Field of view in mm, used to compute voxel size.

  • num_objects – Fixed number of cylinders to generate. Mutually exclusive with vf_range.

  • vf_range – Range of target volume fractions. Cylinders are added until the volume fraction is reached. Mutually exclusive with num_objects.

  • diameter_range – Range of cylinder diameters in mm.

  • allow_overlap – If False, cylinders are only added if they contribute new voxels.

  • device – Target compute device, e.g. ‘cuda’ or ‘cpu’.

  • seed – Random seed for reproducibility.

Examples

Create 100 random cylinder label maps and save to disk:

>>> shape = (128, 128, 128)
>>> fov = (32.0, 32.0, 32.0)
>>> num_cylinders = 10
>>> fname = "<fname-zarr>"
>>> cylinder_map = Cylinders(output_shape, fov, num_cylinders)
>>> cylinder_map(100, fname)
classmethod from_config(config: Config) Self

Constructs cylinder label map instance from configuration object.

class synthbold.geometries.Shapes(shape: tuple[int, int, int] = (128, 128, 128), J: int = 10, displacement_shape: tuple[int, int, int] = (2, 2, 2), scale: float = 0.2, *, device: str | device = 'cpu', seed: int | None = None)

Bases: BaseGeometry

Random shape mask generator.

Generates masks with J input labels of random generic shapes. Maps are created by first drawing J smoothly varying noise images by sampling voxels from a standard distribution at lower resolution and upsampling to full size. Second, each image is warped with a random smooth deformation field. Third, we create an input mask by assigning, for each voxel, the label corresponding to the image that has the highest intensity (Hoffmann et al., 2021; Hoffmann et al., 2023).

These masks can be used to define random background tissue signal for synthetic BOLD data generation.

Parameters:
  • shape – Matrix size of the target shape mask (X, Y, Z).

  • J – Number of distinct labels.

  • displacement_shape – Matrix size of the low-resolution displacement field.

  • scale – Scale factor of the low-resolution displacement field.

  • device – Target compute device, e.g. ‘cuda’ or ‘cpu’.

  • seed – Random seed for reproducibility.

Raises:

ValueError – If J is less than 1, or if any displacement_shape dimension is less than 1.

Examples

Create 100 random maps and save to disk:

>>> J = 26
>>> shape = (32, 32, 32)
>>> fname = "<fname.zarr>"
>>> shape_mask = Shapes(shape, J)
>>> shape_mask(100, fname)

References

Hoffmann, M. et al. (2021). Learning MRI contrast-agnostic registration. Proc IEEE Int Symp Biomed Imaging.

Hoffmann, M. et al. (2022). SynthMorph: Learning contrast-invariant registration without acquired images. IEEE Trans Med Imaging.

property attrs: dict[str, Any]

Metadata for ZARR/NIfTI storage.

forward() Tensor

Generate random shape mask.

classmethod from_config(config: Config) Self

Constructs shape mask instance from configuration object.

class synthbold.geometries.Spheres(shape: tuple[int, int, int] = (128, 128, 128), fov: tuple[float, float, float] = (1.0, 1.0, 1.0), num_objects: int | None = None, vf_range: tuple[float, float] | None = (0.05, 0.1), diameter_range: tuple[float, float] = (0.05, 2.0), allow_overlap: bool = True, device: str = 'cpu', seed: int | None = None)

Bases: ObjectGeometry

Random sphere mask generator.

Generates random spherical label masks. Follows the same interface as Cylinders; see that class for a full description of the shared parameters.

classmethod from_config(config: Config) Self

Constructs sphere label map instance from configuration object.

class synthbold.geometries.Tetrahedra(shape: tuple[int, int, int] = (128, 128, 128), fov: tuple[float, float, float] = (1.0, 1.0, 1.0), num_objects: int | None = None, vf_range: tuple[float, float] | None = (0.05, 0.1), diameter_range: tuple[float, float] = (0.05, 2.0), allow_overlap: bool = True, device: str = 'cpu', seed: int | None = None)

Bases: ObjectGeometry

Random tetrahedron mask generator.

Generates random tetrahedral label masks. Each tetrahedron is a regular tetrahedron placed at a random position in the volume with a random orientation and a random circumradius drawn uniformly from diameter_range. Follows the same interface as Cylinders; see that class for a full description of the shared parameters.

Examples

Create 100 random tetrahedron label maps and save to disk:

>>> shape = (128, 128, 128)
>>> fov = (32.0, 32.0, 32.0)
>>> num_tetrahedra = 10
>>> fname = "<fname-zarr>"
>>> tetra_map = Tetrahedra(shape, fov, num_tetrahedra)
>>> tetra_map(100, fname)
classmethod from_config(config: Config) Self

Constructs tetrahedron label map instance from configuration object.

class synthbold.geometries.Toroids(shape: tuple[int, int, int] = (128, 128, 128), fov: tuple[float, float, float] = (1.0, 1.0, 1.0), num_objects: int | None = None, vf_range: tuple[float, float] | None = (0.05, 0.1), diameter_range: tuple[float, float] = (2.0, 10.0), tube_ratio_range: tuple[float, float] = (0.1, 0.4), allow_overlap: bool = True, device: str = 'cpu', seed: int | None = None)

Bases: ObjectGeometry

Random toroid mask generator.

Generates random toroidal label masks with set volume fraction. Each torus is placed at a random position in the volume with a random orientation. The major radius (R, distance from the torus center to the tube center) is drawn uniformly from diameter_range after converting from mm to voxels. The tube radius (r) is set as a fraction of the major radius sampled uniformly from tube_ratio_range. Follows the same interface as Cylinders; see that class for a full description of the shared parameters.

Parameters:

tube_ratio_range – Range of r/R, where r is the tube radius. Must be in (0, 1) for a non-self-intersecting ring torus.

Raises:

ValueError – If tube_ratio_range contains a value outside (0, 1).

Examples

Create 100 random toroid label maps and save to disk:

>>> shape = (128, 128, 128)
>>> fov = (32.0, 32.0, 32.0)
>>> num_toroids = 5
>>> fname = "<fname-zarr>"
>>> toroid_map = Toroids(shape, fov, num_toroids)
>>> toroid_map(100, fname)
property attrs: dict[str, Any]

Metadata for ZARR/NIfTI storage.

classmethod from_config(config: Config) Self

Constructs toroid label map instance from configuration object.