visualization

Visualize and animate DRRs in 2D and 3D

2D Visualization

Uses matplotlib and imageio to plot DRRs and animate optimization over DRRs.


source

plot_drr


def plot_drr(
    img:torch.Tensor, title:str | None=None, ticks:bool | None=True, axs:matplotlib.axes._axes.Axes | None=None,
    cmap:str='gray', imshow_kwargs:VAR_KEYWORD
):

Plot an image generated by a DRR module.


source

plot_mask


def plot_mask(
    img:torch.Tensor, axs:matplotlib.axes._axes.Axes,
    colors:list=['rgb(102,194,165)', 'rgb(252,141,98)', 'rgb(141,160,203)', 'rgb(231,138,195)', 'rgb(166,216,84)', 'rgb(255,217,47)', 'rgb(229,196,148)'],
    alpha:float=0.5, return_masks:bool=False
):

Plot a 2D rendered segmentation mask. Meant to be called after plot_drr.


source

animate


def animate(
    out:str | pathlib.Path, # Savepath
    df:pandas.DataFrame, drr:DRR, parameterization:str, convention:str=None, ground_truth:torch.Tensor | None=None,
    verbose:bool=True, dtype:dtype=torch.float32, device:str='cpu', kwargs:VAR_KEYWORD
):

Animate the optimization of a DRR.

df is a pandas.DataFrame with columns ["alpha", "beta", "gamma", "bx", "by", "bz"]. Each row in df is an iteration of optimization with the updated values for that timestep.

3D Visualization

Uses pyvista and trame to interactively visualize DRR geometry in 3D.


source

drr_to_mesh


def drr_to_mesh(
    subject:Subject, # torchio.Subject with a `volume` attribute
    method:str, # Either `surface_nets` or `marching_cubes`
    threshold:float=150, # Min value for marching cubes (Hounsfield units)
    extract_largest:bool=True, # Extract the largest connected component from the mesh
    verbose:bool=True, # Display progress bars for mesh processing steps
):

Convert the CT in a DRR object into a mesh.

If using method=="surface_nets", ensure you have pyvista>=0.43 and vtk>=9.3 installed.

The mesh processing steps are:

  1. Keep only largest connected components (optional)
  2. Smooth
  3. Decimate (if method=="marching_cubes")
  4. Fill any holes
  5. Clean (remove any redundant vertices/edges)

source

labelmap_to_mesh


def labelmap_to_mesh(
    subject:Subject, # torchio.Subject with  a `mask` attribute
    verbose:bool=True, # Display progress bars for mesh processing steps
):

source

img_to_mesh


def img_to_mesh(
    drr:DRR, pose:RigidTransform, calibration:RigidTransform=None, kwargs:VAR_KEYWORD
):

For a given pose (not batched), turn the camera and detector into a mesh. Additionally, render the DRR for the pose. Convert into a texture that can be applied to the detector mesh.


source

add_image


def add_image(
    drr:DRR, pose:RigidTransform, pl:pyvista.Plotter
):

Add a camera to an existing scene.


source

visualize_scene


def visualize_scene(
    drr:DRR, pose:RigidTransform, labelmap:bool=False, grid:bool=True, verbose:bool=False, kwargs:VAR_KEYWORD
):

Given a DRR and a RigidTransform, render the 3D scene in PyVista. **kwargs are passed to drr_to_mesh.