VTK to USD Conversion

Convert VTK mesh files to USD format with animation support.

Class Reference

class physiomotion4d.ConvertVTKToUSD(data_basename, input_polydata, mask_ids=None, compute_normals=False, convert_to_surface=True, times_per_second=24.0, separate_by='none', solid_color=(0.8, 0.8, 0.8), segmenter=None, log_level=20)[source]

Bases: PhysioMotion4DBase

Advanced VTK to USD converter with colormap and anatomical labeling support.

This class extends the basic vtk_to_usd library with: - Support for VTK/PyVista objects (not just files) - Anatomical region labeling via mask_ids - Colormap-based visualization - Automatic topology change detection - Time-series animation

Example Usage:
>>> # Create converter with time-series meshes
>>> converter = ConvertVTKToUSD(
...     data_basename='CardiacModel',
...     input_polydata=meshes,  # List of PyVista/VTK meshes
...     mask_ids={1: 'ventricle', 2: 'atrium'}
... )
>>>
>>> # Configure colormap visualization
>>> converter.set_colormap(
...     color_by_array='transmembrane_potential',
...     colormap='rainbow',
...     intensity_range=(-80.0, 20.0)
... )
>>>
>>> # Convert to USD
>>> stage = converter.convert('output.usd')
__init__(data_basename, input_polydata, mask_ids=None, compute_normals=False, convert_to_surface=True, times_per_second=24.0, separate_by='none', solid_color=(0.8, 0.8, 0.8), segmenter=None, log_level=20)[source]

Initialize converter.

Parameters:
  • data_basename (str) – Base name for USD data (used in prim paths)

  • input_polydata (Sequence[pv.DataSet | vtk.vtkDataSet]) – Sequence of PyVista/VTK meshes (one per time step)

  • mask_ids (Optional[dict[int, str]]) – Optional mapping of label IDs to anatomical region names. If provided, meshes will be split by labeled regions.

  • compute_normals (bool) – Whether to compute vertex normals

  • convert_to_surface (bool) – If True, extract surface from volumetric meshes

  • times_per_second (float) – Time codes per second (default 24.0). For medical imaging time series where each frame = 1 second, use 1.0.

  • separate_by (Literal[‘none’, ‘connectivity’, ‘cell_type’]) – How to split the mesh into sub-prims. ‘none’ keeps the mesh as-is, ‘connectivity’ splits by connected component, ‘cell_type’ splits by face vertex count.

  • solid_color (tuple[float, float, float]) – Default RGB diffuse color in [0, 1] used when no colormap is set.

  • segmenter (Optional[SegmentAnatomyBase]) – Optional SegmentAnatomyBase instance used to classify each mask_ids label into an anatomy group (heart / lung / bone / major_vessels / contrast / soft_tissue / other) so labeled prims are written under /World/{data_basename}/{type}/{label} and materials under /World/Looks/{type}/{label}_material. When None, labels are grouped under a single Anatomy Xform.

  • log_level (int | str) – Logging level

classmethod from_files(data_basename, vtk_files, *, extract_surface=True, separate_by='none', times_per_second=24.0, solid_color=(0.8, 0.8, 0.8), time_codes=None, static_merge=False, mask_ids=None, segmenter=None, log_level=20)[source]

Create a converter by loading VTK files from disk.

Accepts .vtk (legacy), .vtp (PolyData), and .vtu (UnstructuredGrid) files. For time-series input, pass files ordered by time and supply time_codes. For a static scene with multiple disconnected meshes, set static_merge=True.

Parameters:
  • data_basename (str) – Base name for USD prim paths.

  • vtk_files (Sequence[Path | str]) – Paths to VTK files; one file = one time step (or one static mesh).

  • extract_surface (bool) – If True, extract surface from UnstructuredGrid (.vtu) meshes.

  • separate_by (Literal['none', 'connectivity', 'cell_type']) – How to split each mesh into sub-prims.

  • times_per_second (float) – FPS for time-varying animation.

  • solid_color (tuple[float, float, float]) – Default RGB diffuse color in [0, 1].

  • time_codes (Optional[list[float]]) – Explicit time codes aligned to vtk_files. If None, uses sequential integers [0, 1, 2, …].

  • static_merge (bool) – If True, treat each file as a separate mesh object in a single static scene (no time samples).

  • mask_ids (Optional[dict[int, str]]) – Optional anatomical label mapping.

  • segmenter (Optional[SegmentAnatomyBase]) – Optional SegmentAnatomyBase used to group labeled prims by anatomy type. See the ConvertVTKToUSD constructor.

  • log_level (int | str) – Logging level.

Return type:

ConvertVTKToUSD

Returns:

ConvertVTKToUSD instance ready to call .convert().

supports_mesh_type(mesh)[source]

Check if mesh type is supported for conversion.

Parameters:

mesh (pv.DataSet | vtk.vtkDataSet) – PyVista or VTK mesh to check

Returns:

True if mesh type is supported

Return type:

bool

classmethod inspect_file(vtk_file, *, extract_surface=True)[source]

Summarize a VTK file using the same low-level reader as conversion.

This method is intended for experiments, workflows, and CLIs that need diagnostics without importing the advanced vtk_to_usd subpackage directly.

Parameters:
  • vtk_file (Union[Path, str]) – Path to a VTK file (.vtk, .vtp, or .vtu).

  • extract_surface (bool) – If True, extract surfaces from volumetric meshes.

Return type:

dict[str, Any]

Returns:

Dictionary containing geometry counts, bounds, data arrays, and surface cell type counts.

list_available_arrays()[source]

List all point data arrays available across all time steps.

Returns:

Dictionary with array names as keys and metadata as values.

Metadata includes: ‘n_components’, ‘dtype’, ‘range’, ‘present_in_steps’

Return type:

dict

set_colormap(color_by_array=None, colormap='plasma', intensity_range=None)[source]

Configure colormap for visualization.

Parameters:
  • color_by_array (Optional[str]) – Name of point data array to visualize. If None, uses solid colors.

  • colormap (str) – Colormap name. Supports all matplotlib colormaps plus aliases: - ‘plasma’, ‘viridis’, ‘inferno’, ‘magma’ (perceptually uniform) - ‘rainbow’, ‘jet’ (spectral) - ‘hot’, ‘heat’ (heat map, ‘heat’ is alias for ‘hot’) - ‘coolwarm’, ‘seismic’ (diverging) - ‘gray’, ‘grayscale’, ‘grey’, ‘greyscale’ (grayscale) - ‘random’, ‘tab20’ (categorical/discrete colors)

  • intensity_range (Optional[tuple[float, float]]) – Manual (vmin, vmax) range. If None, auto-computed from data.

Returns:

For method chaining

Return type:

self

compute_von_mises_stress(stress_array_name='stress', output_name='von_mises_stress')[source]

Add a scalar von Mises stress array derived from a 9-component stress tensor on every input mesh.

For each mesh in self.input_polydata, looks up stress_array_name in cell_data first (FE stress is typically per-cell), then in point_data, reduces the 9-component tensor to scalar von Mises, and writes the result back to the same data dict under output_name.

Call this between from_files() and convert(). The new array becomes a USD primvar at convert time (vtk_cell_<output_name> or vtk_point_<output_name>) and can be selected as the color_by_array for set_colormap or as the target primvar for USDTools.apply_colormap_from_primvar.

Tensor layout (row-major):

[s_xx, s_xy, s_xz, s_yx, s_yy, s_yz, s_zx, s_zy, s_zz]

Off-diagonal pairs are averaged to symmetrize, which is a no-op for an already-symmetric Cauchy stress tensor.

Formula:

sigma_VM = sqrt(0.5 * [(sxx-syy)^2 + (syy-szz)^2 + (szz-sxx)^2]
                + 3.0 * (sxy^2 + syz^2 + szx^2))
Parameters:
  • stress_array_name (str) – Source array name on the input meshes. Defaults to "stress".

  • output_name (str) – Name under which to store the resulting scalar array. Defaults to "von_mises_stress".

Returns:

For method chaining.

Return type:

self

Raises:

ValueError – If no input mesh contains a 9-component array named stress_array_name in either cell_data or point_data.

convert(output_usd_file, convert_to_surface=None, compute_normals=None)[source]

Convert VTK meshes to USD.

Parameters:
  • output_usd_file (str) – Path to output USD file

  • convert_to_surface (Optional[bool]) – Override convert_to_surface setting

  • compute_normals (Optional[bool]) – Override compute_normals setting

Returns:

Created USD stage

Return type:

Usd.Stage

Raises:

ValueError – If no valid meshes found

classmethod get_log_classes()

Get the list of classes currently showing logs.

Return type:

list[str]

Returns:

List of class names that are allowed to show logs. Empty list if filter is disabled (all classes shown).

Example

>>> classes = PhysioMotion4DBase.get_log_classes()
>>> print(classes)
['RegisterModelsPCA', 'WorkflowFitStatisticalModelToPatient']
log_critical(message, *args)

Log a critical message with optional %-style formatting.

Parameters:
  • message (str) – The critical message to log (can contain %-style placeholders)

  • *args (Any) – Arguments for %-style string formatting

Return type:

None

Example

>>> self.log_critical('System failure at %s', timestamp)
>>> self.log_critical('Critical error: %(msg)s', {'msg': 'Out of memory'})
log_debug(message, *args)

Log a debug message with optional %-style formatting.

Parameters:
  • message (str) – The debug message to log (can contain %-style placeholders)

  • *args (Any) – Arguments for %-style string formatting

Return type:

None

Example

>>> self.log_debug('Processing %s with %d items', filename, count)
>>> self.log_debug('Value is %(value)d', {'value': 42})
log_error(message, *args)

Log an error message with optional %-style formatting.

Parameters:
  • message (str) – The error message to log (can contain %-style placeholders)

  • *args (Any) – Arguments for %-style string formatting

Return type:

None

Example

>>> self.log_error('Failed to load %s: %s', filename, error_msg)
>>> self.log_error('Error code: %(code)d', {'code': 404})
log_info(message, *args)

Log an info message with optional %-style formatting.

Parameters:
  • message (str) – The info message to log (can contain %-style placeholders)

  • *args (Any) – Arguments for %-style string formatting

Return type:

None

Example

>>> self.log_info('Loading file: %s', filepath)
>>> self.log_info('Iteration %(iter)d of %(total)d', {'iter': 5, 'total': 10})
log_progress(current, total, prefix='Progress')

Log progress information.

Parameters:
  • current (int) – Current step/iteration number

  • total (int) – Total number of steps/iterations

  • prefix (str) – Prefix text for the progress message. Default: ‘Progress’

Return type:

None

Example

>>> for i in range(100):
...     self.log_progress(i + 1, 100)
>>> self.log_progress(5, 10, prefix='Processing')

Note

For custom formatted progress messages, use log_info() directly: >>> self.log_info(‘Loading %s: %d/%d’, filename, current, total)

log_section(title, *args, width=70, char='=')

Log a formatted section header with optional %-style formatting.

Useful for visually separating major sections of output.

Parameters:
  • title (str) – The section title (can contain %-style placeholders)

  • *args (Any) – Arguments for %-style string formatting of title

  • width (int) – Total width of the header line. Default: 70

  • char (str) – Character to use for the header line. Default: ‘=’

Return type:

None

Example

>>> self.log_section('Stage 1: Initialization')
>>> self.log_section('Processing file: %s', filename)
>>> self.log_section('Stage %(num)d: %(name)s', {'num': 2, 'name': 'Analysis'})
# Outputs:
# ======================================================================
# Stage 2: Analysis
# ======================================================================
log_warning(message, *args)

Log a warning message with optional %-style formatting.

Parameters:
  • message (str) – The warning message to log (can contain %-style placeholders)

  • *args (Any) – Arguments for %-style string formatting

Return type:

None

Example

>>> self.log_warning('Memory usage at %d%%', usage_percent)
>>> self.log_warning('Parameter %(name)s out of range', {'name': 'threshold'})
classmethod set_log_all_classes()

Enable logging output from all PhysioMotion4D classes.

Disables the class filter so all classes show their logs.

Example

>>> PhysioMotion4DBase.set_log_all_classes()
>>> # Now all classes will show their logs
Return type:

None

classmethod set_log_classes(class_names)

Set which classes should show their logging output.

Only log messages from the specified classes will be displayed. All other classes will have their logs hidden.

Parameters:

class_names (list[str]) – List of class names to show logs from. Example: [“RegisterModelsPCA”, “WorkflowFitStatisticalModelToPatient”]

Return type:

None

Example

>>> PhysioMotion4DBase.set_log_classes(['RegisterModelsPCA'])
>>> # Now only RegisterModelsPCA logs will be shown
classmethod set_log_level(log_level)

Set the logging level for all PhysioMotion4D classes.

Parameters:

log_level (int | str) – Logging level. Can be an integer (logging.DEBUG, logging.INFO, logging.WARNING, logging.ERROR, logging.CRITICAL) or a string (‘DEBUG’, ‘INFO’, ‘WARNING’, ‘ERROR’, ‘CRITICAL’).

Return type:

None

Example

>>> import logging
>>> PhysioMotion4DBase.set_log_level(logging.DEBUG)
>>> # or
>>> PhysioMotion4DBase.set_log_level('DEBUG')

Navigation

USD Anatomy Tools | USD Generation Modules