Scripting Q&A
Answers to common questions about writing scripts with the Volvicon Scripting API. Each answer is a complete, runnable script. Some entries also show a frequent mistake and the correct alternative.
Two conventions apply throughout:
- Start every script with
import ScriptingApi as apiandapp = api.Application(), then obtain operation groups fromapp(for exampleapp.get_surface_operations()). - All API calls use positional arguments only. Keyword arguments (
name=value) are not supported.
Getting Started
Every script begins by importing the module and creating an Application instance. Operation groups (volumes, masks, surfaces, and so on) are obtained from that instance.
How do I start a script and connect to the running Volvicon application?
Import the API module and create an Application instance. This is the entry point for everything else.
import ScriptingApi as api
app = api.Application()
print(f"Volvicon version: {app.get_version()}")
Result: Prints the running application version, confirming the script is connected.
How do I get a specific operations object, such as volume or mask operations?
Operation groups are returned by getter methods on the Application instance. Call the getter, then call methods on the returned object.
import ScriptingApi as api
app = api.Application()
volume_operations = app.get_volume_operations()
mask_operations = app.get_mask_operations()
surface_operations = app.get_surface_operations()
Common mistake
# Wrong: operation classes are not static and are not constructed directly.
volume_operations = api.VolumeOperations()
api.VolumeOperations.get_dimensions("Volume_1")
Why it is wrong: Operation groups must be obtained from the Application instance (for example app.get_volume_operations()). They are not called statically as api.VolumeOperations.method(...) and are not constructed with api.VolumeOperations().
Why do my API calls fail when I use keyword arguments?
The Scripting API accepts positional arguments only. Pass values in order, without name=value.
import ScriptingApi as api
app = api.Application()
mask_operations = app.get_mask_operations()
# Correct: positional arguments in order
mask_operations.smooth_mean_filter(["Mask_1"], 1, 1, 1)
Common mistake
# Wrong: keyword arguments are not supported.
mask_operations.smooth_mean_filter(mask_names=["Mask_1"], radius_x=1, radius_y=1, radius_z=1)
Why it is wrong: The API binds parameters by position. Passing name=value raises an error. Supply the arguments in the documented order instead.
Which imports and name prefixes do Scripting API scripts use?
The only import is import ScriptingApi as api. Every API class, parameters object, and enum is used with the api. prefix, and operation groups are obtained from the Application instance.
import ScriptingApi as api
app = api.Application()
surface_operations = app.get_surface_operations() # operations group from app
# Parameters objects and enums always use the api. prefix
params = api.SurfaceFilterShellsParams()
params.largest_shells = 1
surfaces = app.get_all_surface_names()
if surfaces:
surface_operations.filter_shells(surfaces[0], api.SurfaceFilterShellsMethod.LargestShells, params)
Common mistake
# Wrong: there is no volvicon package, and API names are never used bare.
from volvicon.scripting import SurfaceOperations, SurfaceFilterShellsParams
params = SurfaceFilterShellsParams() # NameError - missing api.
SurfaceOperations.filter_shells(surfaces[0], SurfaceFilterShellsMethod.LargestShells, params)
Why it is wrong: The only import is import ScriptingApi as api. There is no volvicon or volvicon.scripting package, and you never write from ScriptingApi import .... Reference every class, parameters object, and enum through api. (api.SurfaceFilterShellsParams(), api.SurfaceFilterShellsMethod.LargestShells), and obtain operation groups from the app (surface_operations = app.get_surface_operations()), never as a bare SurfaceOperations class.
How do I show a message box or ask the user a yes/no question from a script?
import ScriptingApi as api
app = api.Application()
app.show_message_box("Processing finished.", "Information")
app.show_message_box("Low memory.", "Warning", api.MsgBoxLevel.Warn)
proceed = app.show_question_message_box("Continue with export?", "Confirm")
if proceed:
print("User chose Yes")
How do I undo or redo the last operation in a script?
import ScriptingApi as api
app = api.Application()
app.undo()
app.redo()
How do I get the file path of the currently open project?
import ScriptingApi as api
app = api.Application()
print("Project path:", app.get_project_file_path())
When someone says "create a sphere" or "create a sphere object", should it be a surface or a primitive?
Treat an unqualified shape request as a surface object. Use a primitive only when the request explicitly says "primitive" (for example "sphere primitive" or "primitive object").
import ScriptingApi as api
app = api.Application()
# "create a sphere" / "create a sphere object" -> SURFACE object
surface_operations = app.get_surface_operations()
surface_operations.create_sphere("MySphere", 10.0, [0.0, 0.0, 0.0]) # name, radius, center
# "create a sphere primitive" / "create a primitive sphere" -> PRIMITIVE object
primitive_operations = app.get_primitive_operations()
primitive_operations.create_sphere([0.0, 0.0, 0.0], 10.0, "MySphere") # center, radius, name
Result: Surface shapes are mesh objects created through SurfaceOperations (name first). Primitives are lightweight markers and annotations created through PrimitiveOperations (center first). The same shape names exist in both groups, so the wording of the request decides which one to use.
Projects and Object Management
Projects (.vvcx) hold all volumes, masks, surfaces, volume meshes, measurements, and primitives. Object names are the handles used by almost every operation.
How do I open, save, and close a project?
import ScriptingApi as api
app = api.Application()
app.close_project()
opened = app.open_project("C:/data/scan_project.vvcx")
if opened:
app.save_project("C:/data/scan_project_copy.vvcx")
Result: Closes any open project, opens the given project, then saves a copy.
How do I list all the objects in the current project?
import ScriptingApi as api
app = api.Application()
print("Volumes:", app.get_all_volume_names())
print("Masks:", app.get_all_mask_names())
print("Surfaces:", app.get_all_surface_names())
print("Volume meshes:", app.get_all_volume_mesh_names())
print("Measurements:", app.get_all_measurement_names())
How do I get the active volume, mask, or surface?
The active object is the one many single-target operations act on. Each object type has its own active-name getter.
import ScriptingApi as api
app = api.Application()
print("Active volume:", app.get_active_volume_name())
print("Active mask:", app.get_active_mask_name())
print("Active surface:", app.get_active_surface_name())
How do I rename a volume?
import ScriptingApi as api
app = api.Application()
volumes = app.get_all_volume_names()
if volumes:
app.rename_volume(volumes[0], "CT_Patient_001")
How do I hide all surfaces except one (isolate it)?
Use the isolate helpers to show only the listed objects and hide the rest.
import ScriptingApi as api
app = api.Application()
surfaces = app.get_all_surface_names()
if surfaces:
app.isolate_surfaces([surfaces[0]])
Result: Shows only the first surface and hides every other surface.
How do I duplicate a mask?
import ScriptingApi as api
app = api.Application()
masks = app.get_all_mask_names()
if masks:
duplicated = app.duplicate_masks([masks[0]])
print("Duplicated:", duplicated)
How do I delete specific surfaces, or all surfaces at once?
import ScriptingApi as api
app = api.Application()
# Delete named surfaces
app.delete_surfaces(["Surface_A", "Surface_B"])
# Delete every surface (pass False to skip the confirmation dialog)
app.delete_all_surfaces(False)
How do I rename a measurement or text annotation?
Text annotations are measurement objects, so rename them with app.rename_measurement using the current and new name.
import ScriptingApi as api
app = api.Application()
# A text annotation is listed among the measurement names
print(app.get_all_measurement_names())
app.rename_measurement("Text Annotation 1", "Tumor label")
Result: Each object type has its own rename method on the Application object: rename_volume, rename_mask, rename_surface, rename_volume_mesh, rename_measurement, rename_primitive, and rename_analysis.
How do I rename objects of any type (volume, mask, surface, mesh, measurement, primitive, analysis)?
import ScriptingApi as api
app = api.Application()
app.rename_volume("Volume_1", "CT")
app.rename_mask("Mask_1", "Bone")
app.rename_surface("Surface_1", "Femur")
app.rename_volume_mesh("VolumeMesh_1", "Femur_Mesh")
app.rename_measurement("Distance 1", "Span")
app.rename_primitive("Sphere 001", "Marker")
app.rename_analysis("WallThickness_1", "WT")
How do I set the active object for each type?
import ScriptingApi as api
app = api.Application()
volumes = app.get_all_volume_names()
if volumes:
app.set_active_volume(volumes[0])
masks = app.get_all_mask_names()
if masks:
app.set_active_mask(masks[0])
surfaces = app.get_all_surface_names()
if surfaces:
app.set_active_surface(surfaces[0])
meshes = app.get_all_volume_mesh_names()
if meshes:
app.set_active_volume_mesh(meshes[0])
analyses = app.get_all_analysis_names()
if analyses:
app.set_active_analysis(analyses[0])
How do I duplicate objects of any type?
import ScriptingApi as api
app = api.Application()
app.duplicate_volumes(["Volume_1"])
app.duplicate_masks(["Mask_1"])
app.duplicate_surfaces(["Surface_1"])
app.duplicate_volume_meshes(["VolumeMesh_1"])
app.duplicate_measurements(["Distance 1"])
app.duplicate_primitives(["Sphere 001"])
app.duplicate_analyses(["WallThickness_1"])
How do I delete specific objects or all objects of a type?
Each type has its own delete and delete-all methods (for example delete_masks and delete_all_masks). Pass False to skip the confirmation dialog.
import ScriptingApi as api
app = api.Application()
app.delete_masks(["Mask_1"])
app.delete_all_masks(False)
app.delete_primitives(["Sphere 001"])
app.delete_all_primitives(False)
app.delete_analyses(["WallThickness_1"])
app.delete_all_analyses(False)
How do I show, hide, or isolate objects of any type?
Every object type, including analyses, supports the same visibility helpers: set_visible(...) to show or hide a named set, and isolate(...) to show only one subset of that type.
import ScriptingApi as api
app = api.Application()
app.set_masks_visible(app.get_all_mask_names(), False) # hide all masks
app.isolate_surfaces(["Surface_1"]) # show only this surface
app.set_primitives_visible(["Sphere 001"], True)
app.set_volume_meshes_visible(app.get_all_volume_mesh_names(), True)
app.isolate_analyses(["WallThickness_1"]) # show only this analysis
How do I list the visible objects of each type?
import ScriptingApi as api
app = api.Application()
print("Volumes:", app.get_visible_volume_names())
print("Masks:", app.get_visible_mask_names())
print("Surfaces:", app.get_visible_surface_names())
print("Volume meshes:", app.get_visible_volume_mesh_names())
print("Measurements:", app.get_visible_measurement_names())
print("Primitives:", app.get_visible_primitive_names())
print("Analyses:", app.get_visible_analysis_names())
How do I list, activate, rename, and delete analyses?
import ScriptingApi as api
app = api.Application()
analyses = app.get_all_analysis_names()
print("Analyses:", analyses)
if analyses:
app.set_active_analysis(analyses[0])
print("Active analysis:", app.get_active_analysis_name())
app.rename_analysis(analyses[0], "Inspection")
# app.delete_analyses(["Inspection"])
How do I get the application version and working directory?
import ScriptingApi as api
app = api.Application()
print("Version:", app.get_version())
print("Working directory:", app.get_working_directory())
How do I generate, set the quality of, and remove the 3D preview of masks?
import ScriptingApi as api
app = api.Application()
app.set_mask_3d_preview_quality(api.Mask3dPreviewQuality.Optimal) # Low, Medium, High, Optimal
print("Preview quality:", app.get_mask_3d_preview_quality())
app.generate_mask_3d_preview(app.get_visible_mask_names())
masks = app.get_all_mask_names()
if masks:
app.remove_mask_3d_preview([masks[0]])
app.remove_all_mask_3d_previews()
How do I grab a snapshot as in-memory image data instead of saving a file?
import ScriptingApi as api
app = api.Application()
image = app.grab_snapshot(api.SnapshotType.View3D)
print("Size:", image.width, "x", image.height, "Format:", image.format)
# image.data holds the raw image bytes
Volume Images
Volume operations cover import and export, blank volume creation, property queries, filtering, resampling, cropping, and transforms. Get the group with app.get_volume_operations().
How do I import a 3D image file such as MHA or NIfTI?
import ScriptingApi as api
app = api.Application()
volume_operations = app.get_volume_operations()
volume_name = volume_operations.import_3d_image_from_disk("C:/data/ct_scan.mha")
print("Imported:", volume_name)
Result: Imports the file and returns the new volume name. Supported formats are mha, mhd, nii, nii.gz, nrrd, nhdr, hdr, img.gz, gipl, lsm, and vti.
How do I import a headerless raw volume file?
A raw file stores only the voxel values, so the layout has to be supplied. Every value must match how the file was written.
import ScriptingApi as api
app = api.Application()
volume_operations = app.get_volume_operations()
options = api.RawVolumeImportOptions()
options.voxel_data_type = api.RawVoxelDataType.UnsignedInt16
options.dimension_x = 512
options.dimension_y = 512
options.dimension_z = 300
options.spacing_x = 0.4
options.spacing_y = 0.4
options.spacing_z = 0.8
options.header_size = 0
options.little_endian = True
volume_name = volume_operations.import_raw_volume_from_disk("C:/data/scan.raw", options)
print("Imported:", volume_name)
Result: Imports the file and returns the new volume name. The import fails if the file is smaller than the given dimensions require.
Common mistake
volume_name = volume_operations.import_3d_image_from_disk("C:/data/scan.raw")
Why it is wrong: A raw, vol, bin, or img file carries no dimensions, spacing, or data type, so it cannot be read on its own. This call raises an error telling you to use import_raw_volume_from_disk() instead. For an Analyze image, import the matching .hdr file.
How do I import a DICOM series from a folder?
Discover the series in the directory first, then import the chosen series by its instance UID.
import ScriptingApi as api
app = api.Application()
volume_operations = app.get_volume_operations()
options = api.DicomSeriesImportOptions()
series = volume_operations.get_dicom_series_in_directory("C:/data/dicom", options)
if series:
uid = series[0].series_instance_uid
volume_name = volume_operations.import_dicom_series_from_directory("C:/data/dicom", [uid], options)
print("Imported series:", volume_name)
How do I export a volume to disk?
import ScriptingApi as api
app = api.Application()
volume_operations = app.get_volume_operations()
volumes = app.get_all_volume_names()
if volumes:
volume_operations.export_volume_image_to_disk(volumes[0], "C:/output/volume.mha")
How do I read a volume's dimensions, spacing, and intensity range?
import ScriptingApi as api
app = api.Application()
volume_operations = app.get_volume_operations()
volumes = app.get_all_volume_names()
if volumes:
vol = volumes[0]
dims = volume_operations.get_dimensions(vol)
spacing = volume_operations.get_spacing(vol)
scalar_range = volume_operations.get_scalar_range(vol)
print(f"Dimensions: {dims}")
print(f"Spacing (mm): {spacing}")
print(f"Intensity range: {scalar_range[0]} to {scalar_range[1]}")
How do I create an empty (blank) volume?
import ScriptingApi as api
app = api.Application()
volume_operations = app.get_volume_operations()
volume_name = volume_operations.create_blank_volume(
"New_Volume",
[256, 256, 128], # dimensions [x, y, z] in voxels
[0.5, 0.5, 1.0], # spacing [x, y, z] in mm
api.VoxelDataType.Unsigned8Bit
)
print("Created:", volume_name)
How do I apply a Gaussian smoothing filter to a volume?
import ScriptingApi as api
app = api.Application()
volume_operations = app.get_volume_operations()
volumes = app.get_all_volume_names()
if volumes:
volume_operations.gaussian_filter(
[volumes[0]],
1.0, # standard deviation
3.0, # radius factor
True # apply in 3D
)
How do I resample a volume to a new size and spacing?
import ScriptingApi as api
app = api.Application()
volume_operations = app.get_volume_operations()
volumes = app.get_all_volume_names()
if volumes:
volume_operations.resample(
[volumes[0]],
[512, 512, 256], # target dimensions
[0.5, 0.5, 0.5], # target spacing in mm
api.Interpolation.Linear, # volume interpolation
api.Interpolation.Nearest # mask interpolation
)
How do I crop a volume to a bounding region?
Crop bounds are given in millimetres as [xMin, xMax, yMin, yMax, zMin, zMax].
import ScriptingApi as api
app = api.Application()
volume_operations = app.get_volume_operations()
volumes = app.get_all_volume_names()
if volumes:
volume_operations.crop([volumes[0]], [-50.0, 50.0, -50.0, 50.0, -30.0, 30.0])
How do I apply a morphological dilation to a volume?
For volumes, the operation enum is api.MorphologicalOperation.
import ScriptingApi as api
app = api.Application()
volume_operations = app.get_volume_operations()
volumes = app.get_all_volume_names()
if volumes:
volume_operations.morphological_operation(
[volumes[0]],
api.MorphologicalOperation.Dilate,
[2, 2, 2] # ball radius in voxels
)
Common mistake
# Wrong: that enum belongs to mask operations, not volume operations.
volume_operations.morphological_operation([volumes[0]], api.MorphologicalOperationType.Dilate, [2, 2, 2])
Why it is wrong: Volume morphology uses api.MorphologicalOperation. Mask morphology uses api.MorphologicalOperationType. The two enums are not interchangeable.
How do I combine two volumes by addition?
import ScriptingApi as api
app = api.Application()
volume_operations = app.get_volume_operations()
volumes = app.get_all_volume_names()
if len(volumes) >= 2:
result = volume_operations.combine(
volumes[0],
volumes[1],
"", # target name (unused when creating new)
api.CombineOperation.Addition,
True # create a new volume
)
print("Combined volume:", result)
How do I flip a volume or swap two of its axes?
import ScriptingApi as api
app = api.Application()
volume_operations = app.get_volume_operations()
volumes = app.get_all_volume_names()
if volumes:
volume_operations.flip([volumes[0]], api.FlipAxis.X, False) # axis, about origin
volume_operations.swap_axes([volumes[0]], api.SwapAxesPair.XY) # XY, XZ, or YZ
How do I window the intensities of a volume into a display range?
import ScriptingApi as api
app = api.Application()
volume_operations = app.get_volume_operations()
volumes = app.get_all_volume_names()
if volumes:
volume_operations.intensity_windowing_filter(
[volumes[0]],
10, # window minimum
120, # window maximum
0, # output minimum
255 # output maximum
)
How do I read the gray value of a volume at a world coordinate?
import ScriptingApi as api
app = api.Application()
volume_operations = app.get_volume_operations()
volumes = app.get_all_volume_names()
if volumes:
gray = volume_operations.get_gray_value_at_world_coordinates(volumes[0], [0.0, 0.0, 0.0])
print("Gray value at origin:", gray)
How do I recenter a volume at the origin and change its spacing?
import ScriptingApi as api
app = api.Application()
volume_operations = app.get_volume_operations()
volumes = app.get_all_volume_names()
if volumes:
volume_operations.center_at_origin([volumes[0]])
volume_operations.change_spacing([volumes[0]], [1.0, 1.0, 1.0]) # mm
How do I add voxel padding around a volume?
import ScriptingApi as api
app = api.Application()
volume_operations = app.get_volume_operations()
volumes = app.get_all_volume_names()
if volumes:
volume_operations.pad(
[volumes[0]],
[10, 10, 5], # lower padding [x, y, z] in voxels
[10, 10, 5] # upper padding [x, y, z] in voxels
)
How do I blank out everything outside a mask in a volume?
import ScriptingApi as api
app = api.Application()
volume_operations = app.get_volume_operations()
volumes = app.get_all_volume_names()
masks = app.get_all_mask_names()
if volumes and masks:
volume_operations.apply_mask_to_volume(volumes[0], masks[0], 0) # value outside the mask
How do I rescale a volume intensity range to 0-255?
import ScriptingApi as api
app = api.Application()
volume_operations = app.get_volume_operations()
volumes = app.get_all_volume_names()
if volumes:
volume_operations.rescale_intensity_filter([volumes[0]], 0, 255)
How do I compute a signed distance map from a volume?
import ScriptingApi as api
app = api.Application()
volume_operations = app.get_volume_operations()
volumes = app.get_all_volume_names()
if volumes:
volume_operations.signed_maurer_distance_map_filter([volumes[0]])
Masks and Segmentation
Mask operations cover creation, thresholding, region growing, morphology, Boolean combinations, region filtering, and conversion to surfaces. Get the group with app.get_mask_operations().
How do I segment a volume by intensity threshold?
Configure a ThresholdParams object, then call threshold with the volume name.
import ScriptingApi as api
app = api.Application()
mask_operations = app.get_mask_operations()
volumes = app.get_all_volume_names()
if volumes:
params = api.ThresholdParams()
params.lower_threshold = 200
params.upper_threshold = 3000
params.fill_cavities = False
params.filter_regions = False
mask_name = mask_operations.threshold(volumes[0], params)
print("Created mask:", mask_name)
How do I keep only the largest connected region of a threshold mask?
import ScriptingApi as api
app = api.Application()
mask_operations = app.get_mask_operations()
volumes = app.get_all_volume_names()
if volumes:
params = api.ThresholdParams()
params.lower_threshold = 200
params.upper_threshold = 3000
params.filter_regions = True
params.keep_largest = True
mask_name = mask_operations.threshold(volumes[0], params)
How do I grow a region from a seed point?
import ScriptingApi as api
app = api.Application()
mask_operations = app.get_mask_operations()
volumes = app.get_all_volume_names()
masks = app.get_all_mask_names()
if volumes and masks:
params = api.RegionGrowSegmentationParams()
params.source_mask_name = masks[0]
params.seeds = [[100.0, 100.0, 50.0]] # world coordinates
params.multiple_layer = True
mask_name = mask_operations.region_grow(volumes[0], params)
How do I create a new empty mask with a specific color?
import ScriptingApi as api
app = api.Application()
mask_operations = app.get_mask_operations()
# autoColor=False, then RGB in 0.0-1.0
mask_name = mask_operations.create_mask("Red_Mask", False, [1.0, 0.0, 0.0])
print("Created:", mask_name)
How do I dilate or erode a mask?
For masks, the operation enum is api.MorphologicalOperationType.
import ScriptingApi as api
app = api.Application()
mask_operations = app.get_mask_operations()
masks = app.get_all_mask_names()
if masks:
mask_operations.morphological_operation(
[masks[0]],
api.MorphologicalOperationType.Dilate, # or Erode, Open, Close
[2, 2, 2] # ball radius in voxels
)
How do I combine two masks with a Boolean union?
import ScriptingApi as api
app = api.Application()
mask_operations = app.get_mask_operations()
masks = app.get_all_mask_names()
if len(masks) >= 2:
result = mask_operations.boolean(
masks[0],
[masks[1]],
"", # target name (unused when creating new)
api.BooleanOperation.Union, # or Intersection, Difference
True # create a new mask
)
print("Result mask:", result)
How do I remove small disconnected regions from a mask?
import ScriptingApi as api
app = api.Application()
mask_operations = app.get_mask_operations()
masks = app.get_all_mask_names()
if masks:
mask_operations.filter_regions(
[masks[0]],
False, # keep largest regions
0, # number of largest regions
100 # minimum region size in voxels
)
How do I fill holes and internal cavities in a mask?
import ScriptingApi as api
app = api.Application()
mask_operations = app.get_mask_operations()
masks = app.get_all_mask_names()
if masks:
mask_operations.cavity_fill([masks[0]], False) # fully connected = False
mask_operations.fill_holes([masks[0]], 5) # 5 iterations
How do I convert a mask to a surface mesh?
import ScriptingApi as api
app = api.Application()
mask_operations = app.get_mask_operations()
masks = app.get_all_mask_names()
if masks:
params = api.MaskToSurfaceParams()
params.smoothing = True
params.smooth_iterations = 10
params.triangle_reduction = True
params.triangle_reduction_percent = 50
surfaces = mask_operations.convert_to_surface_objects([masks[0]], params)
print("Created surfaces:", surfaces)
How do I split a multi-label mask into individual masks?
Pass the volume, the multi-label mask, whether to keep only the largest labels, and how many to keep.
import ScriptingApi as api
app = api.Application()
mask_operations = app.get_mask_operations()
volumes = app.get_all_volume_names()
masks = app.get_all_mask_names()
if volumes and masks:
split = mask_operations.split_multi_label_mask(volumes[0], masks[0], True, 1)
print("Split masks:", split)
How do I refine a mask by smoothing it and filling cavities?
import ScriptingApi as api
app = api.Application()
mask_operations = app.get_mask_operations()
masks = app.get_all_mask_names()
if masks:
mask_operations.smooth_median_filter([masks[0]], 1, 1, 1) # radius x, y, z (voxels)
mask_operations.cavity_fill([masks[0]])
How do I check whether a mask is multi-label and list its labels?
import ScriptingApi as api
app = api.Application()
mask_operations = app.get_mask_operations()
masks = app.get_all_mask_names()
if masks and mask_operations.is_multilabel_mask(masks[0]):
for label in mask_operations.get_mask_labels(masks[0]):
print(f"Label {label.value}: {label.annotation}")
else:
print("Mask is single-label (or no masks present).")
How do I merge several masks into one multi-label mask?
import ScriptingApi as api
app = api.Application()
mask_operations = app.get_mask_operations()
masks = app.get_all_mask_names()
if len(masks) >= 2:
merged = mask_operations.merge_into_multi_label_mask(
masks,
"", # target name (unused when creating new)
True, # create a new mask
False # remove the input masks
)
print("Merged multi-label mask:", merged)
How do I compute statistics for each label in a multi-label mask?
import ScriptingApi as api
app = api.Application()
mask_operations = app.get_mask_operations()
measure_operations = app.get_measure_operations()
masks = app.get_all_mask_names()
volumes = app.get_all_volume_names()
if masks and volumes and mask_operations.is_multilabel_mask(masks[0]):
requested = [api.LabelStatisticType.VoxelCount, api.LabelStatisticType.Volume]
result = measure_operations.compute_per_label_mask_statistics(masks[0], volumes[0], requested)
print("Per-label entries:", len(result.label_statistics))
How do I create a multi-label mask from an already-labeled volume?
create_masks_by_segmentation reads label values from the volume; set the last argument to True to pack them into one multi-label mask.
import ScriptingApi as api
app = api.Application()
volume_operations = app.get_volume_operations()
volumes = app.get_all_volume_names()
if volumes:
mask_names = volume_operations.create_masks_by_segmentation(
[volumes[0]],
1, # lower threshold (label value)
255, # upper threshold (label value)
True # create a multi-label mask
)
print("Created masks:", mask_names)
How do I count the regions in a mask and keep only the largest ones?
import ScriptingApi as api
app = api.Application()
mask_operations = app.get_mask_operations()
masks = app.get_all_mask_names()
if masks:
count = mask_operations.count_regions_in_mask(masks[0])
print("Regions:", count)
mask_operations.keep_largest_regions([masks[0]], 3) # keep the 3 largest
How do I invert or binarize a mask?
import ScriptingApi as api
app = api.Application()
mask_operations = app.get_mask_operations()
masks = app.get_all_mask_names()
if masks:
mask_operations.invert_masks([masks[0]])
mask_operations.binarize([masks[0]])
How do I grow or shrink a mask by a distance in millimetres?
import ScriptingApi as api
app = api.Application()
mask_operations = app.get_mask_operations()
masks = app.get_all_mask_names()
if masks:
mask_operations.grow_masks([masks[0]], 2.0) # grow by 2 mm
mask_operations.shrink_masks([masks[0]], 1.0) # shrink by 1 mm
How do I segment using dynamic region growing from a seed point?
Threshold-based dynamic region growing expands from seed points while staying within an intensity range.
import ScriptingApi as api
app = api.Application()
mask_operations = app.get_mask_operations()
volumes = app.get_all_volume_names()
if volumes:
params = api.DynamicRegionGrowThresholdSegmentationParams()
params.seeds = [[100.0, 100.0, 50.0]] # world coordinates
params.lower_threshold = 100
params.upper_threshold = 500
params.fill_cavities = True
params.multiple_layer = True
mask_name = mask_operations.dynamic_region_grow_threshold(volumes[0], params)
print("Created mask:", mask_name)
How do I compute partial-volume results for a mask against its volume?
partial_volume_calculation evaluates the listed masks against the source volume gray values.
import ScriptingApi as api
app = api.Application()
mask_operations = app.get_mask_operations()
volumes = app.get_all_volume_names()
masks = app.get_all_mask_names()
if volumes and masks:
mask_operations.partial_volume_calculation(volumes[0], [masks[0]])
How do I read the labels and annotations of a multi-label mask?
import ScriptingApi as api
app = api.Application()
mask_operations = app.get_mask_operations()
masks = app.get_all_mask_names()
if masks and mask_operations.is_multilabel_mask(masks[0]):
for label in mask_operations.get_mask_labels(masks[0]):
print("Value:", label.value, "Annotation:", label.annotation, "Color:", label.color)
How do I merge several labels of a multi-label mask into one?
import ScriptingApi as api
app = api.Application()
mask_operations = app.get_mask_operations()
masks = app.get_all_mask_names()
if masks:
mask_operations.combine_labels_in_multi_label_mask(masks[0], [1, 2, 3])
How do I remove specific labels from a multi-label mask?
import ScriptingApi as api
app = api.Application()
mask_operations = app.get_mask_operations()
masks = app.get_all_mask_names()
if masks:
mask_operations.remove_labels_from_mask(masks[0], [4, 5])
How do I create a new mask from selected labels of a multi-label mask?
import ScriptingApi as api
app = api.Application()
mask_operations = app.get_mask_operations()
volumes = app.get_all_volume_names()
masks = app.get_all_mask_names()
if volumes and masks:
new_mask = mask_operations.create_new_mask_from_labels(volumes[0], masks[0], [1, 2])
print("New mask:", new_mask)
How do I convert a multi-label mask into a normal (single-label) mask?
import ScriptingApi as api
app = api.Application()
mask_operations = app.get_mask_operations()
masks = app.get_all_mask_names()
if masks:
mask_operations.convert_multi_label_mask_to_normal_mask([masks[0]])
Surfaces
Surface operations create primitive meshes, import and export files, transform geometry, run Boolean operations, process meshes, and diagnose or repair defects. Get the group with app.get_surface_operations(). Surface primitives are created with name first, then size, then center.
How do I create a surface sphere?
Use SurfaceOperations.create_sphere. The signature is name, radius, center; ring and sector resolution are optional.
import ScriptingApi as api
app = api.Application()
surface_operations = app.get_surface_operations()
sphere = surface_operations.create_sphere("MySphere", 10.0, [0.0, 0.0, 0.0])
print("Created surface:", sphere)
Result: Creates a surface object named "MySphere" with radius 10 mm centred at the origin.
Common mistake
# Wrong: this creates a primitive annotation object, not a surface object,
# and its argument order is center, radius, name.
primitive_operations = app.get_primitive_operations()
primitive_operations.create_sphere([0.0, 0.0, 0.0], 10.0, "MySphere")
Why it is wrong: A surface sphere is a mesh surface object created by SurfaceOperations.create_sphere(name, radius, center). PrimitiveOperations.create_sphere(center, radius, name) creates a lightweight primitive annotation, not a surface. Match the object type the question asks for.
How do I create a surface sphere with a specific mesh resolution?
import ScriptingApi as api
app = api.Application()
surface_operations = app.get_surface_operations()
sphere = surface_operations.create_sphere(
"HiResSphere",
10.0, # radius
[0.0, 0.0, 0.0], # center
64, # rings (latitude resolution)
64 # sectors (longitude resolution)
)
How do I create a surface cylinder?
import ScriptingApi as api
app = api.Application()
surface_operations = app.get_surface_operations()
cylinder = surface_operations.create_cylinder(
"MyCylinder",
5.0, # radius
20.0, # height
[0.0, 0.0, 0.0], # center
36, # resolution
True, # capping
2 # direction (0=X, 1=Y, 2=Z)
)
How do I create a surface box or cube?
import ScriptingApi as api
app = api.Application()
surface_operations = app.get_surface_operations()
box = surface_operations.create_box("MyBox", 20.0, 15.0, 10.0, [0.0, 0.0, 0.0], 10)
cube = surface_operations.create_cube("MyCube", 15.0, [0.0, 0.0, 0.0], 10)
How do I change the color of a surface object?
Surface appearance is controlled through the render-properties group, obtained from the surface operations object.
import ScriptingApi as api
app = api.Application()
surface_operations = app.get_surface_operations()
surface_render_properties_operations = surface_operations.get_render_properties_operations()
surfaces = app.get_all_surface_names()
if surfaces:
surface_render_properties_operations.set_color([surfaces[0]], [1.0, 0.0, 0.0]) # red
Common mistake
# Wrong: the Application object has no render-properties getter.
render = app.get_render_properties_operations() # AttributeError
render = app.get_surface_render_properties_operations() # AttributeError
Why it is wrong: Render properties are reached from the surface operations object: surface_operations.get_render_properties_operations(). The Application object has no app.get_render_properties_operations() and no app.get_surface_render_properties_operations() — both raise AttributeError. You may also construct one with api.SurfaceRenderPropertiesOperations(), but the calls are still instance methods, not static api.SurfaceRenderPropertiesOperations.set_color(...).
How do I create a 3D coordinate axes from surface arrows with X, Y, Z colors?
Create three surface arrows along each axis, then color them through the render-properties group.
import ScriptingApi as api
app = api.Application()
surface_operations = app.get_surface_operations()
surface_render_properties_operations = surface_operations.get_render_properties_operations()
origin = [0.0, 0.0, 0.0]
axis_length = 100.0
shaft_radius = 2.0
tip_length = axis_length / 8
tip_radius = shaft_radius * 2
# create_arrow(name, totalLength, shaftRadius, tipLength, tipRadius, center, resolution, direction)
x_axis = surface_operations.create_arrow("X-Axis", axis_length, shaft_radius, tip_length, tip_radius, origin, 32, 0)
y_axis = surface_operations.create_arrow("Y-Axis", axis_length, shaft_radius, tip_length, tip_radius, origin, 32, 1)
z_axis = surface_operations.create_arrow("Z-Axis", axis_length, shaft_radius, tip_length, tip_radius, origin, 32, 2)
# For positive-direction axes only, place each arrow center halfway along its own axis:
# x_axis = surface_operations.create_arrow("X-Axis", axis_length, shaft_radius, tip_length, tip_radius, [axis_length / 2, 0.0, 0.0], 32, 0)
# Optional: you can also translate already-created arrows to move them into positive space.
# surface_operations.translate([x_axis], [axis_length / 2, 0.0, 0.0])
surface_render_properties_operations.set_color([x_axis], [1.0, 0.0, 0.0]) # red
surface_render_properties_operations.set_color([y_axis], [0.0, 1.0, 0.0]) # green
surface_render_properties_operations.set_color([z_axis], [0.0, 0.0, 1.0]) # blue
Common mistake
# Wrong: set_axis_labels_color targets bounding-box axis labels, not the
# surface color, and it is an instance method, not a static api call.
api.SurfaceRenderPropertiesOperations.set_axis_labels_color([x_axis], [1.0, 0.0, 0.0, 1.0])
Why it is wrong: Use set_color on the render-properties instance to color surface objects. set_axis_labels_color styles the bounding-box axis labels, not surfaces. The render-properties group comes from surface_operations.get_render_properties_operations() — there is no app.get_render_properties_operations() on the Application object — and its methods are instance methods, not static api.SurfaceRenderPropertiesOperations.method(...) calls.
How do I move (translate) a surface versus apply a full transformation matrix?
translate takes a 3-element offset vector [dx, dy, dz]. transform takes a 16-element 4x4 matrix. They are separate methods with different argument shapes; do not pass one shape to the other.
import ScriptingApi as api
app = api.Application()
surface_operations = app.get_surface_operations()
surfaces = app.get_all_surface_names()
if surfaces:
# Move by an offset vector (millimetres)
surface_operations.translate([surfaces[0]], [10.0, 0.0, -5.0])
# Apply a full 4x4 transformation, flattened to 16 values
matrix = [
1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0,
]
surface_operations.transform([surfaces[0]], matrix)
# For rotation or scaling, use the dedicated helpers (no matrix needed)
surface_operations.rotate([surfaces[0]], 45.0, [0.0, 0.0, 1.0]) # angle, axis
surface_operations.scale([surfaces[0]], [2.0, 2.0, 2.0]) # per-axis factors
Common mistake
# Wrong: translate takes a 3-element offset, not a matrix.
surface_operations.translate([surfaces[0]], matrix) # 16 values -> error
# Wrong: transform takes a 16-element matrix, not a 3-element offset.
surface_operations.transform([surfaces[0]], [10.0, 0.0, -5.0]) # 3 values -> error
# Wrong: there is no translate(name, dx, dy, dz); pass one [x, y, z] list.
surface_operations.translate([surfaces[0]], 10.0, 0.0, -5.0)
Why it is wrong: translate(names, [dx, dy, dz]) moves objects by an offset vector (3 values); transform(names, matrix) applies a 4x4 transformation flattened to 16 values. They are not interchangeable, and neither accepts loose scalars — coordinates always go in one list. Prefer rotate(names, angle, axis) and scale(names, factors) over hand-building a matrix. translate/transform/rotate/scale also exist on volume-mesh operations; volumes have transform(names, matrix) and translate_origin(names, [dx, dy, dz]) but no volume_operations.translate.
How do I import a surface mesh from an STL file?
import ScriptingApi as api
app = api.Application()
surface_operations = app.get_surface_operations()
surface_name = surface_operations.import_surface_from_disk("C:/data/part.stl")
print("Imported:", surface_name)
Result: Supported import formats are stl, ply, obj, wrl, vrml, gltf, glb, amf, step, stp, iges, igs, vtp, and xyz.
How do I export a surface to an STL file?
The third argument selects ASCII (True) or binary (False).
import ScriptingApi as api
app = api.Application()
surface_operations = app.get_surface_operations()
surfaces = app.get_all_surface_names()
if surfaces:
surface_operations.export_surface_to_disk(surfaces[0], "C:/output/model.stl", False)
How do I run a Boolean union between two surfaces?
import ScriptingApi as api
app = api.Application()
surface_operations = app.get_surface_operations()
surfaces = app.get_all_surface_names()
if len(surfaces) >= 2:
result = surface_operations.boolean_operation(
surfaces[0],
[surfaces[1]],
"Union_Result",
api.SurfaceBooleanOperation.Union, # or Intersection, Difference
True # create a new surface
)
print("Result:", result)
How do I smooth a surface mesh?
import ScriptingApi as api
app = api.Application()
surface_operations = app.get_surface_operations()
surfaces = app.get_all_surface_names()
if surfaces:
surface_operations.smooth_smart(
[surfaces[0]],
20, # iterations
0.01, # smoothing factor (0.0001-1.0)
True, # smooth feature edges
85 # feature angle in degrees
)
How do I reduce or decimate the triangle count of a surface?
Use reduce for general-purpose surface simplification and decimation.
import ScriptingApi as api
app = api.Application()
surface_operations = app.get_surface_operations()
surfaces = app.get_all_surface_names()
if surfaces:
surface_operations.reduce(
[surfaces[0]],
50.0, # desired percentage
True, # use desired percentage
3000 # desired triangles (used when above is False)
)
How do I decimate a surface mesh to a target triangle count?
import ScriptingApi as api
app = api.Application()
surface_operations = app.get_surface_operations()
surfaces = app.get_all_surface_names()
if surfaces:
surface_operations.reduce(
[surfaces[0]],
0.0, # ignored when use desired percentage is False
False, # use desired triangle count
3000
)
How do I make a surface watertight by diagnosing and fixing defects?
import ScriptingApi as api
app = api.Application()
surface_operations = app.get_surface_operations()
surfaces = app.get_all_surface_names()
if surfaces:
checks = api.SurfaceDiagnosticsChecks()
result = surface_operations.diagnose_surface(surfaces[0], checks)
print("Holes:", result.holes, "Self-intersections:", result.intersection_triangles)
surface_operations.fix_surface(surfaces[0], checks)
How do I keep only the largest shell of a surface?
import ScriptingApi as api
app = api.Application()
surface_operations = app.get_surface_operations()
surfaces = app.get_all_surface_names()
if surfaces:
params = api.SurfaceFilterShellsParams()
params.largest_shells = 1
surface_operations.filter_shells(surfaces[0], api.SurfaceFilterShellsMethod.LargestShells, params)
How do I hollow a surface to a given wall thickness?
import ScriptingApi as api
app = api.Application()
surface_operations = app.get_surface_operations()
surfaces = app.get_all_surface_names()
if surfaces:
hollowed = surface_operations.hollow(
[surfaces[0]],
api.SurfaceHollowMethod.Fast,
api.SurfaceHollowDirection.Inward,
2.0, # wall thickness
api.SurfaceHollowResolution.Medium,
True # create a new surface
)
How do I subdivide a surface to increase its mesh detail?
import ScriptingApi as api
app = api.Application()
surface_operations = app.get_surface_operations()
surfaces = app.get_all_surface_names()
if surfaces:
surface_operations.subdivide(
[surfaces[0]],
api.SurfaceSubdivisionMethod.Loop, # Linear, Loop, Butterfly, Adaptive
1, # subdivisions
1.0 # max edge length (Adaptive only)
)
How do I subtract one surface from another (Boolean difference)?
import ScriptingApi as api
app = api.Application()
surface_operations = app.get_surface_operations()
surfaces = app.get_all_surface_names()
if len(surfaces) >= 2:
result = surface_operations.boolean_operation(
surfaces[0], # A
[surfaces[1]], # B is subtracted from A
"Difference_Result",
api.SurfaceBooleanOperation.Difference,
True # create a new surface
)
print("Result:", result)
How do I run a robust Boolean operation on complex surfaces (voxel-based)?
Voxel Boolean is more robust than mesh Boolean for surfaces with intersections or thin walls.
import ScriptingApi as api
app = api.Application()
surface_operations = app.get_surface_operations()
surfaces = app.get_all_surface_names()
if len(surfaces) >= 2:
result = surface_operations.voxel_boolean_operation(
surfaces[0],
[surfaces[1]],
"VoxelBoolean_Result",
api.SurfaceBooleanOperation.Union,
api.SurfaceVoxelizeMethod.Fast, # Fast or Accurate
[1, 1, 1], # voxel spacing
True, # smooth artifacts
True # create a new surface
)
How do I merge surfaces or split a surface into its shells?
import ScriptingApi as api
app = api.Application()
surface_operations = app.get_surface_operations()
surfaces = app.get_all_surface_names()
if len(surfaces) >= 2:
merged = surface_operations.merge(
surfaces[:2], "Merged_Surface",
True, # merge coincident points
False, # remove input surfaces
True # create a new surface
)
if surfaces:
shells = surface_operations.split(surfaces[0], 0, False) # 0 = all shells
print("Shells:", shells)
How do I convert a surface into a mask?
Conversion samples the surface into the active volume grid, so a volume must be active first.
import ScriptingApi as api
app = api.Application()
surface_operations = app.get_surface_operations()
surfaces = app.get_all_surface_names()
volumes = app.get_all_volume_names()
if surfaces and volumes:
app.set_active_volume(volumes[0])
masks = surface_operations.convert_to_mask(
[surfaces[0]],
api.SurfaceVoxelConversionMethod.Filled, # Filled, ThickContour, ThinContour, LineContour
True # smooth artifacts
)
print("Created masks:", masks)
How do I create a cone surface?
import ScriptingApi as api
app = api.Application()
surface_operations = app.get_surface_operations()
cone = surface_operations.create_cone(
"MyCone",
8.0, # base radius
15.0, # height
[0.0, 0.0, 0.0], # center
36, # resolution
True, # capping
2 # direction (0=X, 1=Y, 2=Z)
)
How do I create a torus surface?
import ScriptingApi as api
app = api.Application()
surface_operations = app.get_surface_operations()
torus = surface_operations.create_torus(
"MyTorus",
3.0, # inner (ring) radius
10.0, # outer (total) radius
[0.0, 0.0, 0.0], # center
36, # resolution
2 # direction (0=X, 1=Y, 2=Z)
)
How do I create an ellipsoid surface with three radii?
import ScriptingApi as api
app = api.Application()
surface_operations = app.get_surface_operations()
ellipsoid = surface_operations.create_ellipsoid(
"MyEllipsoid",
10.0, 7.0, 5.0, # radius X, Y, Z
[0.0, 0.0, 0.0], # center
36, 36 # rings, sectors
)
How do I create a platonic solid surface such as an icosahedron?
import ScriptingApi as api
app = api.Application()
surface_operations = app.get_surface_operations()
solid = surface_operations.create_platonic_solid(
"MyIcosahedron",
api.PlatonicSolidType.Icosahedron, # Tetrahedron, Octahedron, Icosahedron, Dodecahedron
10.0, # radius
[0.0, 0.0, 0.0] # center
)
How do I keep only the overlapping region of two surfaces (Boolean intersection)?
import ScriptingApi as api
app = api.Application()
surface_operations = app.get_surface_operations()
surfaces = app.get_all_surface_names()
if len(surfaces) >= 2:
result = surface_operations.boolean_operation(
surfaces[0],
[surfaces[1]],
"Intersection_Result",
api.SurfaceBooleanOperation.Intersection,
True
)
How do I fill holes in a surface mesh?
import ScriptingApi as api
app = api.Application()
surface_operations = app.get_surface_operations()
surfaces = app.get_all_surface_names()
if surfaces:
surface_operations.fill_holes(
surfaces[0],
100, # maximum hole size
api.SurfaceHoleFillingMethod.Angle # Angle, Area, or EarCut
)
How do I uniformly remesh a surface using a voxel-based method?
import ScriptingApi as api
app = api.Application()
surface_operations = app.get_surface_operations()
surfaces = app.get_all_surface_names()
if surfaces:
surface_operations.voxel_remesh(
[surfaces[0]],
api.SurfaceVoxelizeMethod.Fast, # Fast or Accurate
[1, 1, 1], # voxel spacing
True # smooth artifacts
)
How do I decimate a surface while preserving its sharp features?
import ScriptingApi as api
app = api.Application()
surface_operations = app.get_surface_operations()
surfaces = app.get_all_surface_names()
if surfaces:
surface_operations.reduce_by_features(
[surfaces[0]],
60.0, # feature angle (degrees)
50.0, # desired percentage
True, # use desired percentage
3000 # desired triangles (used when above is False)
)
How do I reduce or decimate a mesh by joining nearby points?
import ScriptingApi as api
app = api.Application()
surface_operations = app.get_surface_operations()
surfaces = app.get_all_surface_names()
if surfaces:
surface_operations.reduce_by_nearby_points(
[surfaces[0]],
0.5 # nearby-point distance in project units
)
Primitives (Annotations and References)
Primitives are lightweight geometric markers for visualization, measurement references, and annotations. They are distinct from surface mesh objects. Get the group with app.get_primitive_operations(). Primitive creators take the position/points first, then size, then the name.
How do I create a primitive sphere as a reference marker?
Use PrimitiveOperations.create_sphere. The argument order is center, radius, name.
import ScriptingApi as api
app = api.Application()
primitive_operations = app.get_primitive_operations()
sphere = primitive_operations.create_sphere([100.0, 100.0, 100.0], 15.0, "Sphere 001")
print("Created primitive:", sphere)
Result: Adds a primitive sphere of radius 15 mm. For a mesh surface sphere instead, use surface_operations.create_sphere(name, radius, center).
How do I create a primitive point marker?
import ScriptingApi as api
app = api.Application()
primitive_operations = app.get_primitive_operations()
point = primitive_operations.create_point([10.0, 20.0, 30.0], 2.0, "Point 001")
How do I draw a line primitive between two points?
import ScriptingApi as api
app = api.Application()
primitive_operations = app.get_primitive_operations()
line = primitive_operations.create_line([0.0, 0.0, 0.0], [100.0, 0.0, 0.0], 1.0, "Line X")
How do I build a coordinate system using primitive arrows?
Primitive arrows take a start point, end point, shaft radius, tip radius, tip length, and name.
import ScriptingApi as api
app = api.Application()
primitive_operations = app.get_primitive_operations()
origin = [0.0, 0.0, 0.0]
length = 100.0
x_axis = primitive_operations.create_arrow(origin, [length, 0.0, 0.0], 2.0, 6.0, 0.2, "X-Axis")
y_axis = primitive_operations.create_arrow(origin, [0.0, length, 0.0], 2.0, 6.0, 0.2, "Y-Axis")
z_axis = primitive_operations.create_arrow(origin, [0.0, 0.0, length], 2.0, 6.0, 0.2, "Z-Axis")
primitive_operations.set_color([x_axis], [1.0, 0.0, 0.0])
primitive_operations.set_color([y_axis], [0.0, 1.0, 0.0])
primitive_operations.set_color([z_axis], [0.0, 0.0, 1.0])
How do I change a primitive's color and opacity?
Primitive appearance is set directly on the primitive operations object (no separate render-properties group).
import ScriptingApi as api
app = api.Application()
primitive_operations = app.get_primitive_operations()
primitives = app.get_all_primitive_names()
if primitives:
primitive_operations.set_color([primitives[0]], [1.0, 0.0, 0.0])
primitive_operations.set_opacity([primitives[0]], 0.8)
How do I convert a primitive into a surface object for mesh operations?
import ScriptingApi as api
app = api.Application()
primitive_operations = app.get_primitive_operations()
primitives = app.get_all_primitive_names()
if primitives:
surfaces = primitive_operations.convert_to_surfaces([primitives[0]])
print("Created surfaces:", surfaces)
How do I list all primitives of a given type, such as spheres?
import ScriptingApi as api
app = api.Application()
primitive_operations = app.get_primitive_operations()
spheres = primitive_operations.get_primitive_names_by_type(api.PrimitiveType.Sphere)
print("Sphere primitives:", spheres)
How do I create a cylinder primitive between two points?
Primitive cylinders are defined by two end points and a radius. Use this only when the request explicitly asks for a primitive.
import ScriptingApi as api
app = api.Application()
primitive_operations = app.get_primitive_operations()
cylinder = primitive_operations.create_cylinder([50.0, 50.0, 0.0], [50.0, 50.0, 100.0], 10.0, "Cylinder 001")
How do I read the center and bounding box of a primitive?
import ScriptingApi as api
app = api.Application()
primitive_operations = app.get_primitive_operations()
primitives = app.get_all_primitive_names()
if primitives:
center = primitive_operations.get_center(primitives[0])
bounds = primitive_operations.get_bounds(primitives[0])
print("Center:", center)
print("Bounds [xmin, xmax, ymin, ymax, zmin, zmax]:", bounds)
How do I create a spline primitive through control points?
import ScriptingApi as api
app = api.Application()
primitive_operations = app.get_primitive_operations()
control_points = [[0.0, 0.0, 0.0], [50.0, 50.0, 20.0], [100.0, 30.0, 40.0], [150.0, 80.0, 30.0]]
spline = primitive_operations.create_spline(control_points, 5.0, False, "Spline 001") # points, radius, closed loop, name
How do I create cuboid and plane primitives?
import ScriptingApi as api
app = api.Application()
primitive_operations = app.get_primitive_operations()
cuboid = primitive_operations.create_cuboid([300.0, 300.0, 50.0], 50.0, 30.0, 20.0, "Cuboid 001") # center, width, height, depth, name
plane = primitive_operations.create_plane([0.0, 0.0, 0.0], 100.0, 80.0, "Plane 001") # center, width, height, name
Measurements
Measurement operations create and query 3D measurements such as points, distances, angles, and contours. Get the group with app.get_measurement_operations(). Do not confuse it with app.get_measure_operations(), which computes statistics — see the first entry below.
What is the difference between measurement operations and measure operations, and which do I use?
Two similarly named groups do different jobs. Use measurement_operations to create and edit 3D measurement objects; use measure_operations to compute numeric results (statistics, histograms, mesh quality, primitive fitting).
import ScriptingApi as api
app = api.Application()
# measurement_operations -> create/edit measurement OBJECTS in the scene
measurement_operations = app.get_measurement_operations()
distance = measurement_operations.create_distance([0.0, 0.0, 0.0], [100.0, 0.0, 0.0], "Span")
# measure_operations -> COMPUTE statistics and other numeric results
measure_operations = app.get_measure_operations()
volumes = app.get_all_volume_names()
if volumes:
params = api.VolumeStatisticsParams()
params.target = api.VolumeStatisticsTarget.WholeVolume
stats = measure_operations.compute_volume_statistics(volumes[0], params)
print("Mean intensity:", stats.mean_intensity)
Common mistake
# Wrong: statistics live on measure_operations, not measurement_operations.
app.get_measurement_operations().compute_volume_statistics("Volume_1") # AttributeError
# Wrong: creating a measurement lives on measurement_operations, not measure_operations.
app.get_measure_operations().create_distance([0.0, 0.0, 0.0], [1.0, 0.0, 0.0], "Span") # AttributeError
Why it is wrong: The two groups are not interchangeable. get_measurement_operations() builds and edits measurement objects (create_point, create_distance, create_angle, create_contour, set_color, snap_to_surface). get_measure_operations() computes results (compute_volume_statistics, generate_histogram, compute_whole_mask_statistics, analyze_surface_mesh_quality, fit_primitive_to_surface). Choose the group by the action: create an annotation versus compute a number.
How do I create a distance measurement between two points?
import ScriptingApi as api
app = api.Application()
measurement_operations = app.get_measurement_operations()
distance = measurement_operations.create_distance([0.0, 0.0, 0.0], [100.0, 50.0, 25.0], "MyDistance")
print("Created:", distance)
How do I read the value of a distance measurement?
import ScriptingApi as api
app = api.Application()
measurement_operations = app.get_measurement_operations()
names = app.get_all_measurement_names()
if names:
distance = measurement_operations.get_distance_measurement(names[0])
print(f"Distance: {distance.distance} mm")
How do I create an angle measurement?
import ScriptingApi as api
app = api.Application()
measurement_operations = app.get_measurement_operations()
angle = measurement_operations.create_angle(
[0.0, 0.0, 0.0], # first point
[50.0, 0.0, 0.0], # vertex
[50.0, 50.0, 0.0], # third point
"MyAngle"
)
How do I add a text annotation in the 3D scene?
import ScriptingApi as api
app = api.Application()
measurement_operations = app.get_measurement_operations()
annotation = measurement_operations.create_annotation([50.0, 50.0, 50.0], "Region of interest", "Note 1")
How do I snap a measurement onto a surface?
import ScriptingApi as api
app = api.Application()
measurement_operations = app.get_measurement_operations()
measurements = app.get_all_measurement_names()
surfaces = app.get_all_surface_names()
if measurements and surfaces:
measurement_operations.snap_to_surface([measurements[0]], surfaces[0])
How do I read the area and perimeter of a contour measurement?
import ScriptingApi as api
app = api.Application()
measurement_operations = app.get_measurement_operations()
points = [[0.0, 0.0, 0.0], [100.0, 0.0, 0.0], [100.0, 100.0, 0.0], [0.0, 100.0, 0.0]]
name = measurement_operations.create_contour(points, True, "MyContour") # closed loop
contour = measurement_operations.get_contour_measurement(name)
print(f"Area: {contour.area}, Perimeter: {contour.perimeter}")
How do I get the formatted value string of a measurement?
import ScriptingApi as api
app = api.Application()
measurement_operations = app.get_measurement_operations()
names = app.get_all_measurement_names()
if names:
print(measurement_operations.get_measurement_value_string(names[0]))
How do I change the color, line width, and annotation type of a measurement?
import ScriptingApi as api
app = api.Application()
measurement_operations = app.get_measurement_operations()
names = app.get_all_measurement_names()
if names:
measurement_operations.set_color([names[0]], [1.0, 0.0, 0.0])
measurement_operations.set_line_width([names[0]], 2.0)
measurement_operations.set_annotation_type([names[0]], api.MeasurementAnnotationType.NameAndValue)
How do I create circle and diameter measurements?
import ScriptingApi as api
app = api.Application()
measurement_operations = app.get_measurement_operations()
circle = measurement_operations.create_circle([0.0, 0.0, 0.0], [10.0, 0.0, 0.0], "MyCircle")
diameter = measurement_operations.create_diameter([0.0, 0.0, 0.0], [100.0, 0.0, 0.0], [50.0, 50.0, 0.0], "MyDiameter")
Statistics and Measure Operations
Measure operations compute histograms, volume and mask statistics, mesh quality, primitive fitting, and mask comparison. Get the group with app.get_measure_operations().
How do I compute a histogram for a volume?
import ScriptingApi as api
app = api.Application()
measure_operations = app.get_measure_operations()
volumes = app.get_all_volume_names()
if volumes:
params = api.HistogramParams()
params.number_of_bins = 64
params.target = api.VolumeStatisticsTarget.WholeVolume
histogram = measure_operations.generate_histogram(volumes[0], params)
print("Total count:", histogram.total_count)
How do I compute intensity statistics for a volume?
import ScriptingApi as api
app = api.Application()
measure_operations = app.get_measure_operations()
volumes = app.get_all_volume_names()
if volumes:
params = api.VolumeStatisticsParams()
params.target = api.VolumeStatisticsTarget.WholeVolume
stats = measure_operations.compute_volume_statistics(volumes[0], params)
print(f"Mean: {stats.mean_intensity}, Std dev: {stats.standard_deviation}")
How do I compare two masks with the Dice coefficient?
import ScriptingApi as api
app = api.Application()
measure_operations = app.get_measure_operations()
masks = app.get_all_mask_names()
if len(masks) >= 2:
comparison = measure_operations.compare_masks(masks[0], masks[1])
print(f"Dice coefficient: {comparison.dice_coefficient}")
How do I get statistics for a mask, such as volume and voxel count?
import ScriptingApi as api
app = api.Application()
measure_operations = app.get_measure_operations()
masks = app.get_all_mask_names()
volumes = app.get_all_volume_names()
if masks:
requested = [api.LabelStatisticType.VoxelCount, api.LabelStatisticType.Volume]
volume_name = volumes[0] if volumes else ""
stats = measure_operations.compute_whole_mask_statistics(masks[0], volume_name, requested)
print("Total voxel count:", stats.total_voxel_count)
How do I fit a sphere to a surface and get its center?
import ScriptingApi as api
app = api.Application()
measure_operations = app.get_measure_operations()
surfaces = app.get_all_surface_names()
if surfaces:
params = api.PrimitiveFittingParams()
params.primitive_type = api.PrimitiveFittingType.Sphere
params.source = api.PrimitiveFittingSource.Surface
fit = measure_operations.fit_primitive_to_surface(surfaces[0], params)
print("Fitted primitive:", fit.primitive_name, "center:", fit.center)
How do I get intensity statistics (mean, min, max, std) for a mask?
Request the statistic types you need, then read the totals and the per-label entries.
import ScriptingApi as api
app = api.Application()
measure_operations = app.get_measure_operations()
masks = app.get_all_mask_names()
volumes = app.get_all_volume_names()
if masks and volumes:
requested = [
api.LabelStatisticType.VoxelCount,
api.LabelStatisticType.Volume,
api.LabelStatisticType.MeanIntensity,
api.LabelStatisticType.StandardDeviation,
]
result = measure_operations.compute_whole_mask_statistics(masks[0], volumes[0], requested)
print("Total volume:", result.total_volume)
if result.label_statistics:
label = result.label_statistics[0]
print("Mean intensity:", label.mean_intensity, "Std dev:", label.standard_deviation)
Volume Meshes and FEM
Volume mesh operations import, export, transform, and convert volume meshes (tetrahedral and non-tetrahedral). FEM operations build solver models on a mesh. Get the groups with app.get_volume_mesh_operations() and volume_mesh_operations.get_fem_operations().
How do I convert a surface into a tetrahedral volume mesh?
Set the meshing parameters on the surface first, then convert.
import ScriptingApi as api
app = api.Application()
surface_operations = app.get_surface_operations()
surfaces = app.get_all_surface_names()
if surfaces:
params = api.VolumeMeshParams()
params.resolution = api.VolumeMeshResolution.Moderate
params.optimize_surface = True
surface_operations.set_volume_mesh_parameters(surfaces[0], params)
meshes = surface_operations.convert_to_volume_mesh([surfaces[0]], api.VolumeMeshMethod.Auto3D)
print("Created volume meshes:", meshes)
How do I import a volume mesh file?
import ScriptingApi as api
app = api.Application()
volume_mesh_operations = app.get_volume_mesh_operations()
mesh_name = volume_mesh_operations.import_volume_mesh_from_disk("C:/data/mesh.vtu")
print("Imported:", mesh_name)
Which solver file formats can I import?
The same call imports every supported format and detects the format automatically from the file. Each import creates a new volume mesh object.
import ScriptingApi as api
app = api.Application()
volume_mesh_operations = app.get_volume_mesh_operations()
# Supported: VTK (.vtu, .vtk), Abaqus / CalculiX (.inp),
# Nastran (.bdf, .nas), LS-DYNA (.k, .dyn, .key), ANSYS (.cdb),
# Gmsh (.msh), Fluent (.msh), and OpenFOAM.
mesh_name = volume_mesh_operations.import_volume_mesh_from_disk("C:/data/model.inp")
print("Imported:", mesh_name)
# .msh is shared by Gmsh and Fluent; the format is told apart by file content.
# For OpenFOAM, pass the .foam marker file or the case directory itself
# (a folder with the mesh files, a polyMesh folder, or constant/polyMesh).
foam = volume_mesh_operations.import_volume_mesh_from_disk("C:/data/case")
How do I import several solver files at once?
import ScriptingApi as api
app = api.Application()
volume_mesh_operations = app.get_volume_mesh_operations()
names = volume_mesh_operations.import_volume_meshes_from_disk([
"C:/data/part_a.cdb",
"C:/data/part_b.bdf",
])
print("Imported:", names)
What does Volvicon import from a solver mesh, and what is skipped?
Importing a solver file creates a volume mesh and attaches its FEM model where the file provides one. Solid and shell cells (including hexahedra, wedges, and pyramids) are imported; higher-order elements become linear; 1D beams/trusses and contact/target helper elements are not imported as mesh elements.
import ScriptingApi as api
app = api.Application()
volume_mesh_operations = app.get_volume_mesh_operations()
fem_operations = volume_mesh_operations.get_fem_operations()
mesh = volume_mesh_operations.import_volume_mesh_from_disk("C:/data/model.cdb")
if mesh:
stats = fem_operations.get_model_statistics(mesh)
print("Nodes:", stats.node_count, "Elements:", stats.element_count)
print("Materials:", stats.material_count,
"Sets:", stats.node_set_count + stats.element_set_count,
"Surfaces:", stats.surface_count)
How do I convert a volume mesh back to a surface?
import ScriptingApi as api
app = api.Application()
volume_mesh_operations = app.get_volume_mesh_operations()
meshes = app.get_all_volume_mesh_names()
if meshes:
surfaces = volume_mesh_operations.convert_to_surfaces([meshes[0]])
print("Created surfaces:", surfaces)
How do I set up an FEM model and assign a steel material?
FEM operations are reached from the volume mesh operations group.
import ScriptingApi as api
app = api.Application()
volume_mesh_operations = app.get_volume_mesh_operations()
fem_operations = volume_mesh_operations.get_fem_operations()
meshes = app.get_all_volume_mesh_names()
if meshes:
mesh = meshes[0]
fem_operations.create_fem_model(mesh)
steel = fem_operations.add_material_from_preset(mesh, api.FemMaterialPreset.Steel, "StructuralSteel")
print("Material:", steel)
How do I export an FEM model to a solver format (Abaqus, Nastran, LS-DYNA, Gmsh, Fluent, OpenFOAM)?
Solver export goes through the FEM operations group, which writes the FEM model (materials, sets, surfaces, parts) — not just geometry. Each format has a matching export_to_* function (export_to_abaqus, export_to_nastran, export_to_ls_dyna, export_to_gmsh, export_to_fluent, export_to_open_foam), or use the generic export_to_format with a format selector.
import ScriptingApi as api
app = api.Application()
volume_mesh_operations = app.get_volume_mesh_operations()
fem_operations = volume_mesh_operations.get_fem_operations()
meshes = app.get_all_volume_mesh_names()
if meshes:
common = api.FemExportOptions()
common.model_name = "MyModel"
abaqus = api.FemAbaqusExportOptions()
abaqus.common = common
result = fem_operations.export_to_abaqus(meshes[0], "C:/output/model.inp", abaqus)
print("Export success:", result.success)
How do I export an FEM model to Gmsh or Fluent?
Gmsh and Fluent both use the .msh extension but are distinct writers. Each takes its own typed options object.
import ScriptingApi as api
app = api.Application()
volume_mesh_operations = app.get_volume_mesh_operations()
fem_operations = volume_mesh_operations.get_fem_operations()
meshes = app.get_all_volume_mesh_names()
if meshes:
gmsh = api.FemGmshExportOptions()
fem_operations.export_to_gmsh(meshes[0], "C:/output/model_gmsh.msh", gmsh)
fluent = api.FemFluentExportOptions()
fem_operations.export_to_fluent(meshes[0], "C:/output/model_fluent.msh", fluent)
How do I export a volume mesh to a VTU file?
export_volume_mesh_to_disk writes only the VTK mesh geometry (.vtu / .vtk). It does not write the attached FEM model — use the FEM operations export_to_* functions for solver formats.
import ScriptingApi as api
app = api.Application()
volume_mesh_operations = app.get_volume_mesh_operations()
meshes = app.get_all_volume_mesh_names()
if meshes:
volume_mesh_operations.export_volume_mesh_to_disk(meshes[0], "C:/output/mesh.vtu", False) # isASCII=False
How do I read the vertex and cell counts of a volume mesh?
import ScriptingApi as api
app = api.Application()
volume_mesh_operations = app.get_volume_mesh_operations()
meshes = app.get_all_volume_mesh_names()
if meshes:
geometry = volume_mesh_operations.get_geometry_data(meshes[0])
print("Vertices:", len(geometry.vertices), "Cells:", len(geometry.cell_sizes))
How do I translate, rotate, or scale a volume mesh?
import ScriptingApi as api
app = api.Application()
volume_mesh_operations = app.get_volume_mesh_operations()
meshes = app.get_all_volume_mesh_names()
if meshes:
volume_mesh_operations.translate([meshes[0]], [10.0, 5.0, 0.0]) # mm
volume_mesh_operations.rotate([meshes[0]], 45.0, [0.0, 0.0, 1.0], [0.0, 0.0, 0.0], True) # angle, axis, center, about centroid
volume_mesh_operations.scale([meshes[0]], [1.5, 1.5, 1.5])
How do I set a volume mesh to wireframe and change its color?
import ScriptingApi as api
app = api.Application()
volume_mesh_operations = app.get_volume_mesh_operations()
volume_mesh_render_properties_operations = volume_mesh_operations.get_render_properties_operations()
meshes = app.get_all_volume_mesh_names()
if meshes:
volume_mesh_render_properties_operations.set_representation([meshes[0]], api.VolumeMeshRepresentation.Wireframe)
volume_mesh_render_properties_operations.set_color([meshes[0]], [0.2, 0.6, 0.8])
volume_mesh_render_properties_operations.set_opacity([meshes[0]], 0.8)
Registration
Registration aligns a movable object to a fixed object. Objects are described with api.GlobalRegistrationObject (a name and a type). Get the group with app.get_registration_operations().
How do I align one surface to another using ICP (point matching)?
import ScriptingApi as api
app = api.Application()
registration_operations = app.get_registration_operations()
surfaces = app.get_all_surface_names()
if len(surfaces) >= 2:
movable = api.GlobalRegistrationObject()
movable.name = surfaces[0]
movable.type = api.GlobalRegistrationObjectType.Surface
fixed = api.GlobalRegistrationObject()
fixed.name = surfaces[1]
fixed.type = api.GlobalRegistrationObjectType.Surface
params = api.SurfaceRegistrationParams()
params.algorithm = api.GlobalRegistrationSurfaceAlgorithm.PointMatching
result = registration_operations.global_registration(
[movable], fixed, params, api.ImageRegistrationParams(), True
)
print("Success:", result.success, "RMSE:", result.rmse_millimeters)
How do I register two volumes with a rigid transform?
import ScriptingApi as api
app = api.Application()
registration_operations = app.get_registration_operations()
volumes = app.get_all_volume_names()
if len(volumes) >= 2:
movable = api.GlobalRegistrationObject()
movable.name = volumes[0]
movable.type = api.GlobalRegistrationObjectType.Volume
fixed = api.GlobalRegistrationObject()
fixed.name = volumes[1]
fixed.type = api.GlobalRegistrationObjectType.Volume
image_params = api.ImageRegistrationParams()
image_params.algorithm = api.GlobalRegistrationImageAlgorithm.Rigid6DOF
result = registration_operations.global_registration(
[movable], fixed, api.SurfaceRegistrationParams(), image_params, True
)
print("Success:", result.success)
How do I align two surfaces using corresponding landmark points?
Provide matching landmark lists (at least three pairs) for the movable and fixed objects.
import ScriptingApi as api
app = api.Application()
registration_operations = app.get_registration_operations()
surfaces = app.get_all_surface_names()
if len(surfaces) >= 2:
movable = api.GlobalRegistrationObject()
movable.name = surfaces[0]
movable.type = api.GlobalRegistrationObjectType.Surface
fixed = api.GlobalRegistrationObject()
fixed.name = surfaces[1]
fixed.type = api.GlobalRegistrationObjectType.Surface
movable_landmarks = [[10.0, 20.0, 30.0], [15.0, 25.0, 35.0], [20.0, 30.0, 40.0]]
fixed_landmarks = [[0.0, 0.0, 0.0], [5.0, 5.0, 5.0], [10.0, 10.0, 10.0]]
result = registration_operations.landmark_registration(
[movable], fixed, movable_landmarks, fixed_landmarks,
api.SurfaceRegistrationParams(), api.ImageRegistrationParams(),
False, # also run global registration fine-tuning
True # calculate RMSE
)
print("Success:", result.success, "RMSE:", result.landmark_rmse_millimeters)
How do I register surfaces using feature matching instead of ICP?
import ScriptingApi as api
app = api.Application()
registration_operations = app.get_registration_operations()
surfaces = app.get_all_surface_names()
if len(surfaces) >= 2:
movable = api.GlobalRegistrationObject()
movable.name = surfaces[0]
movable.type = api.GlobalRegistrationObjectType.Surface
fixed = api.GlobalRegistrationObject()
fixed.name = surfaces[1]
fixed.type = api.GlobalRegistrationObjectType.Surface
params = api.SurfaceRegistrationParams()
params.algorithm = api.GlobalRegistrationSurfaceAlgorithm.FeatureMatching
feature = params.feature_matching
feature.global_iterations = 3
feature.overlap_radius = 10.0
feature.curvature_threshold = 0.001
params.feature_matching = feature
result = registration_operations.global_registration(
[movable], fixed, params, api.ImageRegistrationParams(), True
)
print("Success:", result.success, "RMSE:", result.rmse_millimeters)
How do I align two volumes using corresponding landmark points?
Provide matching landmark lists (at least three pairs) for the moving and fixed volumes.
import ScriptingApi as api
app = api.Application()
registration_operations = app.get_registration_operations()
volumes = app.get_all_volume_names()
if len(volumes) >= 2:
moving = api.GlobalRegistrationObject()
moving.name = volumes[0]
moving.type = api.GlobalRegistrationObjectType.Volume
fixed = api.GlobalRegistrationObject()
fixed.name = volumes[1]
fixed.type = api.GlobalRegistrationObjectType.Volume
moving_landmarks = [[10.0, 20.0, 30.0], [15.0, 25.0, 35.0], [20.0, 30.0, 40.0]]
fixed_landmarks = [[0.0, 0.0, 0.0], [5.0, 5.0, 5.0], [10.0, 10.0, 10.0]]
result = registration_operations.landmark_registration(
[moving], fixed, moving_landmarks, fixed_landmarks,
api.SurfaceRegistrationParams(), api.ImageRegistrationParams(),
False, # also run global registration fine-tuning
True # calculate RMSE
)
print("Success:", result.success, "RMSE:", result.landmark_rmse_millimeters)
Analysis
Analysis operations create, run, and read results for wall thickness, deviation, curvature, extrema, gray value, and void/inclusion studies. Get the group with app.get_analysis_operations().
How do I run a wall thickness analysis on a surface?
import ScriptingApi as api
app = api.Application()
analysis_operations = app.get_analysis_operations()
surface_name = app.get_active_surface_name()
if surface_name:
params = api.WallThicknessParams()
params.method = api.WallThicknessMethod.RayCasting
params.max_wall_thickness = 20.0
params.search_angle = 20.0
name = analysis_operations.create_wall_thickness_analysis_surface("WallThickness_1", surface_name, params)
analysis_operations.run_analysis(name)
results = analysis_operations.get_wall_thickness_analysis_results(name)
print("Mean wall thickness:", results.statistics.mean_value)
How do I run a deviation analysis between two surfaces?
import ScriptingApi as api
app = api.Application()
analysis_operations = app.get_analysis_operations()
surfaces = app.get_all_surface_names()
if len(surfaces) >= 2:
params = api.DeviationParams()
params.method = api.DeviationMethod.Signed
name = analysis_operations.create_deviation_analysis_surface_vs_surface("Deviation_1", surfaces[0], surfaces[1], params)
analysis_operations.run_analysis(name)
results = analysis_operations.get_deviation_analysis_results(name)
print("Mean deviation:", results.statistics.mean_value)
How do I detect voids (porosity) in a volume?
import ScriptingApi as api
app = api.Application()
analysis_operations = app.get_analysis_operations()
volume_name = app.get_active_volume_name()
if volume_name:
params = api.VoidInclusionParams()
params.mode = api.VoidInclusionTargetType.Void
params.method = api.VoidInclusionMethod.Absolute
params.auto_absolute_contrast = True
params.auto_air_gray_value = True
name = analysis_operations.create_void_inclusion_analysis("Voids_1", volume_name, "", params)
analysis_operations.run_analysis(name)
results = analysis_operations.get_void_inclusion_results(name)
print("Total defects:", results.total_defects_found, "Porosity:", results.porosity)
How do I change the color map and value range of an analysis result?
Read the current display settings, adjust the lookup table and range, then apply them back.
import ScriptingApi as api
app = api.Application()
analysis_operations = app.get_analysis_operations()
analyses = app.get_all_analysis_names()
if analyses:
settings = analysis_operations.get_display_settings(analyses[0])
settings.lookup_table_type = api.LookupTableType.ReverseRainbow
settings.range = [1.0, 20.0]
analysis_operations.set_display_settings(analyses[0], settings)
How do I run a curvature analysis on a surface?
import ScriptingApi as api
app = api.Application()
analysis_operations = app.get_analysis_operations()
surface_name = app.get_active_surface_name()
if surface_name:
params = api.CurvatureParams()
params.method = api.CurvatureMethod.Mean # Mean or Gaussian
name = analysis_operations.create_curvature_analysis_surface("Curvature_1", surface_name, params)
analysis_operations.run_analysis(name)
results = analysis_operations.get_curvature_analysis_results(name)
print("Mean curvature:", results.statistics.mean_value)
How do I run a gray-value analysis on a surface using a volume?
import ScriptingApi as api
app = api.Application()
analysis_operations = app.get_analysis_operations()
surface_name = app.get_active_surface_name()
volume_name = app.get_active_volume_name()
if surface_name and volume_name:
params = api.GrayValueParams()
params.mask_preview_surface_quality = api.Mask3dPreviewQuality.Optimal
name = analysis_operations.create_gray_value_analysis_surface("GrayValue_1", surface_name, volume_name, params)
analysis_operations.run_analysis(name)
results = analysis_operations.get_gray_value_analysis_results(name)
print("Mean gray value:", results.statistics.mean_value)
How do I run an extrema analysis to find high and low points along an axis?
import ScriptingApi as api
app = api.Application()
analysis_operations = app.get_analysis_operations()
surface_name = app.get_active_surface_name()
if surface_name:
params = api.ExtremaParams()
params.method = api.ExtremaMethod.MaximumAndMinimum
params.axis = [0.0, 0.0, 1.0]
name = analysis_operations.create_extrema_analysis_surface("Extrema_1", surface_name, params)
analysis_operations.run_analysis(name)
results = analysis_operations.get_extrema_analysis_results(name)
print("Max value:", results.statistics.max_value)
How do I run a wall-thickness analysis on a mask?
import ScriptingApi as api
app = api.Application()
analysis_operations = app.get_analysis_operations()
mask_name = app.get_active_mask_name()
if mask_name:
params = api.WallThicknessParams()
params.method = api.WallThicknessMethod.ShrinkingSphere
params.max_wall_thickness = 10.0
params.search_angle = 20.0
name = analysis_operations.create_wall_thickness_analysis_mask("WallThickness_Mask_1", mask_name, params)
analysis_operations.run_analysis(name)
results = analysis_operations.get_wall_thickness_analysis_results(name)
print("Mean wall thickness:", results.statistics.mean_value)
How do I run a deviation analysis between two masks?
import ScriptingApi as api
app = api.Application()
analysis_operations = app.get_analysis_operations()
masks = app.get_all_mask_names()
if len(masks) >= 2:
params = api.DeviationParams()
params.method = api.DeviationMethod.Signed
name = analysis_operations.create_deviation_analysis_mask_vs_mask("Deviation_MvM", masks[0], masks[1], params)
analysis_operations.run_analysis(name)
results = analysis_operations.get_deviation_analysis_results(name)
print("Mean deviation:", results.statistics.mean_value)
How do I compare a mask against a surface with a deviation analysis?
import ScriptingApi as api
app = api.Application()
analysis_operations = app.get_analysis_operations()
mask_name = app.get_active_mask_name()
surface_name = app.get_active_surface_name()
if mask_name and surface_name:
name = analysis_operations.create_deviation_analysis_mask_vs_surface("Deviation_MvS", mask_name, surface_name, api.DeviationParams())
analysis_operations.run_analysis(name)
results = analysis_operations.get_deviation_analysis_results(name)
print("Mean deviation:", results.statistics.mean_value)
How do I run a curvature analysis on a mask?
import ScriptingApi as api
app = api.Application()
analysis_operations = app.get_analysis_operations()
mask_name = app.get_active_mask_name()
if mask_name:
params = api.CurvatureParams()
params.method = api.CurvatureMethod.Gaussian # Mean or Gaussian
name = analysis_operations.create_curvature_analysis_mask("Curvature_Mask_1", mask_name, params)
analysis_operations.run_analysis(name)
results = analysis_operations.get_curvature_analysis_results(name)
print("Mean curvature:", results.statistics.mean_value)
AI Segmentation
AI segmentation runs models such as TotalSegmentator, nnU-Net, MONAI, and Cellpose-SAM. Get the group with app.get_ai_segmentation(). These tools require a Professional or Ultimate license.
How do I run TotalSegmentator on a volume?
Set the model type, ensure it is installed, configure parameters, then run.
import ScriptingApi as api
app = api.Application()
ai_segmentation = app.get_ai_segmentation()
volumes = app.get_all_volume_names()
if volumes:
ai_segmentation.set_model_type(api.AiSegmentationModelType.TotalSegmentator)
if not ai_segmentation.get_installation_status():
ai_segmentation.install_model()
params = ai_segmentation.get_default_total_segmentator_params()
params.task = "total"
params.fastest = True
params.device = "gpu" # use "cpu" if no compatible GPU is available
masks = ai_segmentation.run_total_segmentator([volumes[0]], params)
print("Generated masks:", masks)
How do I run MONAI segmentation?
import ScriptingApi as api
app = api.Application()
ai_segmentation = app.get_ai_segmentation()
volumes = app.get_all_volume_names()
if volumes:
ai_segmentation.set_model_type(api.AiSegmentationModelType.Monai)
params = api.MonaiParams()
params.bundle_dir = "C:/Users/UserName/.monai/wholeBody_ct_segmentation"
params.device = "gpu"
masks = ai_segmentation.run_monai([volumes[0]], params)
print("Generated masks:", masks)
After AI segmentation, how do I extract the largest label and export it as a surface?
Split the multi-label result, keep the largest connected region, generate a 3D preview, and convert it to a surface.
import ScriptingApi as api
app = api.Application()
mask_operations = app.get_mask_operations()
surface_operations = app.get_surface_operations()
volume_name = app.get_all_volume_names()[0]
active_mask = app.get_active_mask_name()
split = mask_operations.split_multi_label_mask(volume_name, active_mask, True, 1)
mask_operations.filter_regions(split, True, 1, 8)
app.set_mask_3d_preview_quality(api.Mask3dPreviewQuality.Optimal)
app.generate_mask_3d_preview(app.get_visible_mask_names())
surfaces = mask_operations.convert_3d_preview_to_surface_objects()
print("Created surfaces:", surfaces)
How do I check whether an AI model is installed and install it if needed?
Set the model type first, then query installation status. Installing may require running Volvicon as administrator.
import ScriptingApi as api
app = api.Application()
ai_segmentation = app.get_ai_segmentation()
ai_segmentation.set_model_type(api.AiSegmentationModelType.TotalSegmentator)
if not ai_segmentation.get_installation_status():
if not ai_segmentation.install_model():
raise RuntimeError("AI model installation failed; check the saved log file.")
print("Available tasks:", ai_segmentation.get_available_tasks())
How do I run nnU-Net segmentation on a volume?
import ScriptingApi as api
app = api.Application()
ai_segmentation = app.get_ai_segmentation()
volumes = app.get_all_volume_names()
if volumes:
ai_segmentation.set_model_type(api.AiSegmentationModelType.NnUnet)
params = ai_segmentation.get_default_nn_unet_params()
params.models_dir = "C:/Users/UserName/.totalsegmentator/nnunet/results"
params.dataset = "Dataset298_TotalSegmentator_total_6mm_1559subj"
params.configuration = "3d_fullres"
params.folds = [0]
params.npp = 0 # sequential export workers (Windows stability)
params.nps = 0
params.device = "gpu"
masks = ai_segmentation.run_nn_unet([volumes[0]], params)
print("Generated masks:", masks)
How do I run Cellpose-SAM 3D instance segmentation?
Cellpose-SAM labels each detected object with a unique value, suitable for cells, nuclei, and densely packed structures.
import ScriptingApi as api
app = api.Application()
ai_segmentation = app.get_ai_segmentation()
volumes = app.get_all_volume_names()
if volumes:
ai_segmentation.set_model_type(api.AiSegmentationModelType.Cellpose)
params = ai_segmentation.get_default_cellpose_params()
params.mode = "3D"
params.device = "gpu"
params.flow_threshold = 0.4
params.cellprob_threshold = 0.0
params.diameter = 0 # 0 = automatic diameter estimation
params.min_size = 15
masks = ai_segmentation.run_cellpose([volumes[0]], params)
print("Generated masks:", masks)
Views, Camera, and Snapshots
View operations control layouts, scene orientation, window/level, and the camera. Snapshots are saved directly from the Application object. Get the view group with app.get_view_operations().
How do I switch the workspace to a 3D-only layout?
import ScriptingApi as api
app = api.Application()
view_operations = app.get_view_operations()
view_operations.set_layout(api.LayoutPreset.ThreeDOnly)
How do I set the CT window and level for bone?
import ScriptingApi as api
app = api.Application()
view_operations = app.get_view_operations()
view_operations.set_window_level(1000.0, 500.0) # window, level
How do I set the 3D camera to an isometric view and fit the scene?
import ScriptingApi as api
app = api.Application()
view_operations = app.get_view_operations()
view_operations.set_standard_view(api.StandardView.Isometric)
view_operations.reset_3d_view()
How do I save a screenshot of the 3D view to a PNG file?
import ScriptingApi as api
app = api.Application()
app.save_snapshot_to_disk(api.SnapshotType.View3D, "C:/output/view3d.png", "PNG")
How do I save the full application window as an image?
import ScriptingApi as api
app = api.Application()
app.save_snapshot_to_disk(api.SnapshotType.Application, "C:/output/app.png", "PNG")
How do I toggle the crosshair and link the 2D slice views?
import ScriptingApi as api
app = api.Application()
view_operations = app.get_view_operations()
view_operations.set_crosshair_enabled(True)
view_operations.set_slice_views_linked(True)
How do I show or enable 3D contours of surface objects in the 2D slice views?
Contours are a view setting toggled per object type with view_operations.set_3d_contours_enabled(object_type, enabled). The first argument is an api.ContourObjectType value and is required.
import ScriptingApi as api
app = api.Application()
view_operations = app.get_view_operations()
# Show surface intersection contours in the 2D slice views
view_operations.set_3d_contours_enabled(api.ContourObjectType.Surface, True)
# Volume mesh and mask-preview contours use the same method with a different type
# view_operations.set_3d_contours_enabled(api.ContourObjectType.VolumeMesh, True)
# view_operations.set_3d_contours_enabled(api.ContourObjectType.MaskPreview, True)
Result: The intersection of the chosen 3D object type with the current slice plane is drawn as contour lines in all three 2D slice views.
Common mistake
# Wrong: 3D contours are not a render property, and the object type is not optional.
render_properties_operations = app.get_surface_operations().get_render_properties_operations()
render_properties_operations.set_3d_contours_enabled(True) # AttributeError
# Wrong: the api.ContourObjectType argument is required; a single bool fails.
view_operations.set_3d_contours_enabled(True)
Why it is wrong: 3D contours are a view setting, so the method lives on view_operations, not on any get_render_properties_operations() group. Call view_operations.set_3d_contours_enabled(object_type, enabled) with an api.ContourObjectType value (Surface, VolumeMesh, or MaskPreview) as the first argument and the on/off bool as the second. There is no set_3d_contours_enabled on the render-properties groups, and the method never takes a single bool.
How do I show bounding-box outlines for all surfaces (or all volumes) in the 3D view?
Per-object-type outlines are a view setting toggled with view_operations.set_outline_enabled(object_type, enabled). The first argument is an api.WidgetObjectType value and is required.
import ScriptingApi as api
app = api.Application()
view_operations = app.get_view_operations()
# Bounding-box outline for all surface (and mask) objects
view_operations.set_outline_enabled(api.WidgetObjectType.Surface, True)
# Same method, different type, for volumes or volume meshes
# view_operations.set_outline_enabled(api.WidgetObjectType.Volume, True)
# view_operations.set_outline_enabled(api.WidgetObjectType.VolumeMesh, True)
# Corner-only bounding box uses the same api.WidgetObjectType argument
view_operations.set_corner_outline_enabled(api.WidgetObjectType.Surface, True)
Common mistake
# Wrong: the api.WidgetObjectType argument is required; a single bool fails.
view_operations.set_outline_enabled(True)
# Wrong: this is a view toggle, not a per-object render property.
surface_operations = app.get_surface_operations()
surface_render_properties_operations = surface_operations.get_render_properties_operations()
surface_render_properties_operations.set_outline_enabled(True)
Why it is wrong: Bounding-box outlines for a whole object type are a view setting: view_operations.set_outline_enabled(object_type, enabled) and view_operations.set_corner_outline_enabled(object_type, enabled), each taking an api.WidgetObjectType value (Volume, Surface, or VolumeMesh) first and the on/off bool second. They are not methods on a render-properties group and never take a single bool. To toggle the bounding box of one specific volume, use the volume render properties set_bounding_box_visibility instead.
How do I spin or rock the 3D view (animate it) from a script?
Live 3D view animation is a view setting. Set it with view_operations.set_3d_animation_mode(mode) using an api.AnimationMode3d value, and stop it with api.AnimationMode3d.Off.
import ScriptingApi as api
app = api.Application()
view_operations = app.get_view_operations()
# Continuously rotate the scene around the vertical axis
view_operations.set_3d_animation_mode(api.AnimationMode3d.Spin)
# Oscillate back and forth instead
# view_operations.set_3d_animation_mode(api.AnimationMode3d.Rock)
# Stop any active animation
# view_operations.set_3d_animation_mode(api.AnimationMode3d.Off)
Result: Spin rotates the scene around the vertical axis; Rock oscillates it back and forth. The animation runs live in the 3D view until it is set back to Off.
How do I export the slices of a volume as a video from a script?
volume_operations.export_volume_image_as_video steps through a volume's slices along one plane and writes a video file. It returns True on success.
import ScriptingApi as api
app = api.Application()
volume_operations = app.get_volume_operations()
# Sweep the axial (XY) slices into a video at 20 fps with the H.264 codec
ok = volume_operations.export_volume_image_as_video(
"CT", # name of a loaded volume
"C:/output/ct_axial.mp4", # output video file
api.SlicePlane.XY, # XY (axial), XZ (coronal), or YZ (sagittal)
False, # overlay the slice position on each frame
20, # frames per second (>= 1)
"H264") # 4-character codec code, e.g. H264 or MJPG
print("Exported" if ok else "Export failed")
Result: A video that steps through the chosen slice plane of the named volume. Use api.SlicePlane.XZ or api.SlicePlane.YZ for the coronal or sagittal planes.
Can I script the Video Recorder or build a timeline animation (turntable, camera path, opacity or clipping tracks)?
The interactive Video Recorder and its animation timeline (tracks, presets, keyframes, playhead) are GUI tools and are not exposed in the Scripting API. From a script, drive the camera and produce videos or frames with the methods below.
import ScriptingApi as api
app = api.Application()
view_operations = app.get_view_operations()
# Option 1: a live spin or rock animation in the 3D view
view_operations.set_3d_animation_mode(api.AnimationMode3d.Spin)
# Option 2: a slice video of a volume
app.get_volume_operations().export_volume_image_as_video(
"CT", "C:/output/ct_axial.mp4", api.SlicePlane.XY)
# Option 3: build custom frames by rotating the camera and saving snapshots
view_operations.set_3d_animation_mode(api.AnimationMode3d.Off)
for step in range(72):
view_operations.yaw_3d_camera(5.0) # 72 x 5 = 360 degrees
app.save_snapshot_to_disk(api.SnapshotType.View3D, f"C:/output/frame_{step:03d}.png", "PNG")
Result: For a full multi-track timeline animation (camera path, opacity, clipping, slice, and background tracks with presets), use the Video Recorder panel in the GUI (File -> Record Video).
How do I generate a PDF report from a script?
PDF report generation is an interactive feature of the Measure and Analyze ribbon tabs and is not exposed in the Scripting API. From a script, produce the report inputs instead: snapshots, results files, and CSV tables.
import csv
import ScriptingApi as api
app = api.Application()
# Capture figures for the report
app.save_snapshot_to_disk(api.SnapshotType.View3D, "C:/output/view3d.png", "PNG")
app.save_snapshot_to_disk(api.SnapshotType.Scene, "C:/output/scene.png", "PNG")
# Write a results table that can be embedded into a report document
rows = [{"object": name} for name in app.get_all_surface_names()]
with open("C:/output/report_data.csv", "w", newline="") as f:
writer = csv.DictWriter(f, fieldnames=["object"])
writer.writeheader()
writer.writerows(rows)
Result: For a formatted PDF report with embedded 3D scenes and charts, use the Export option in the Measure or Analyze tab in the GUI.
Cone-Beam CT Reconstruction
Reconstruct a 3D volume from cone-beam projection images with the FDK algorithm, then inspect or analyze it. Geometry distances and pixel sizes must match the scanner setup.
How do I reconstruct a 3D volume from cone-beam CT projection images?
Build the ordered list of projection files, configure the geometry, and run the reconstruction. Pass an empty volume name when reconstructing from files.
import os
import ScriptingApi as api
app = api.Application()
volume_operations = app.get_volume_operations()
# Ordered list of projection file paths (zero-padded numbering)
projection_files = [
os.path.join("C:/Samples/Projections", f"FewView_Object{str(i).zfill(6)}.tif")
for i in range(100001, 101002)
]
settings = api.ConeBeamReconstructionSettings()
settings.source_to_detector_distance = 815.19 # mm
settings.source_to_isocenter_distance = 153.48 # mm
settings.detector_pixel_size_x = 0.4 # mm
settings.detector_pixel_size_y = 0.4 # mm
settings.xray_scan_start_angle = 0.0 # degrees
settings.xray_scan_total_angle = 360.0 # degrees
settings.enable_logarithm_conversion = True
settings.auto_crop = True
# Optional: automatic center-of-rotation correction and quality options
settings.enable_auto_detector_offset_x = True
settings.reconstruction_filter = api.CBR_ReconstructionFilter.SheppLogan
settings.filter_cut_frequency = 1.0
settings.noise_reduction_mode = api.CBR_NoiseReductionMode.Median
settings.noise_reduction_level = api.CBR_NoiseReductionLevel.Low
reconstructed_volume = volume_operations.reconstruct_volume_using_cone_beam_reconstruction(
"", # volume name (empty when reconstructing from files)
projection_files,
settings
)
print("Reconstructed volume:", reconstructed_volume)
How do I enable shading and set the blend mode for volume 3D rendering?
import ScriptingApi as api
app = api.Application()
volume_operations = app.get_volume_operations()
volume_render_properties_operations = volume_operations.get_render_properties_operations()
volumes = app.get_all_volume_names()
if volumes:
volume_render_properties_operations.set_blend_mode([volumes[0]], 0)
volume_render_properties_operations.set_shade_enabled([volumes[0]], True)
How do I detect porosity in a reconstructed volume and write the results to disk?
Configure void detection with geometric filtering, run it, read the porosity summary, then export.
import os
import ScriptingApi as api
app = api.Application()
analysis_operations = app.get_analysis_operations()
volume_name = app.get_active_volume_name()
params = api.VoidInclusionParams()
params.mode = api.VoidInclusionTargetType.Void
params.method = api.VoidInclusionMethod.Absolute
params.auto_absolute_contrast = True
params.requested_statistics = ["Volume (mm³)", "Volume fraction (%)", "Sphericity"]
filtering = api.VoidInclusionFilteringParams()
filtering.enable_geometric_filtering = True
filtering.min_voxel_count = 27
filtering.max_count = 100
params.filter_result_params = filtering
vi_name = analysis_operations.create_void_inclusion_analysis("VoidInclusion_1", volume_name, "", params)
analysis_operations.run_analysis(vi_name)
results = analysis_operations.get_void_inclusion_results(vi_name)
print("Total defects:", results.total_defects_found, "Porosity:", results.porosity)
os.makedirs("C:/Samples/Output", exist_ok=True)
analysis_operations.write_void_inclusion_results_to_disk(results, "C:/Samples/Output/void_inclusion.txt")
Reliability and Error Handling
Scripts that run unattended should validate inputs and handle failures so a single bad input does not stop the whole run.
How do I handle errors so a failed step does not crash the whole script?
import ScriptingApi as api
app = api.Application()
volume_operations = app.get_volume_operations()
try:
volume_operations.import_3d_image_from_disk("C:/data/scan.nii")
except Exception as e:
print(f"Import failed: {e}")
app.show_message_box(f"Import failed: {e}", "Error", api.MsgBoxLevel.Error)
How do I check that an object exists before operating on it?
import ScriptingApi as api
app = api.Application()
volumes = app.get_all_volume_names()
if "CT_Head" in volumes:
volume_operations = app.get_volume_operations()
print(volume_operations.get_dimensions("CT_Head"))
else:
app.show_message_box("CT_Head volume not found.", "Warning", api.MsgBoxLevel.Warn)
How do I stop the script when an operation returns no result?
Operations that can return an empty list (segmentation, surface generation) should be checked before the next step uses the result.
import ScriptingApi as api
app = api.Application()
ai_segmentation = app.get_ai_segmentation()
volumes = app.get_all_volume_names()
if not volumes:
raise RuntimeError("No volumes found in project.")
ai_segmentation.set_model_type(api.AiSegmentationModelType.TotalSegmentator)
params = ai_segmentation.get_default_total_segmentator_params()
masks = ai_segmentation.run_total_segmentator([volumes[0]], params)
if len(masks) == 0:
raise RuntimeError("Segmentation returned no masks (cancelled or failed).")
print("Generated masks:", masks)
Batch Processing
Batch pipelines discover input files, loop over them, process each one, export results, and log outcomes. Close the project after each file to free memory.
How do I find all NIfTI files in a folder tree to process?
import os
from pathlib import Path
input_dir = "C:/Data/Input"
files = [str(p) for p in Path(input_dir).rglob("*.nii*")]
print(f"Found {len(files)} files")
How do I process every volume in a folder and continue past failures?
Wrap each file in try/except and close the project in a finally block so one failure does not stop the run or leak memory.
import os
from pathlib import Path
import ScriptingApi as api
app = api.Application()
volume_operations = app.get_volume_operations()
mask_operations = app.get_mask_operations()
input_dir = "C:/Data/Input"
output_dir = "C:/Data/Output"
os.makedirs(output_dir, exist_ok=True)
files = [str(p) for p in Path(input_dir).rglob("*.nii*")]
for i, filepath in enumerate(files):
print(f"[{i + 1}/{len(files)}] {os.path.basename(filepath)}")
try:
volume_name = volume_operations.import_3d_image_from_disk(filepath)
params = api.ThresholdParams()
params.lower_threshold = 200
params.upper_threshold = 3000
mask_name = mask_operations.threshold(volume_name, params)
basename = os.path.basename(filepath).replace(".nii.gz", "").replace(".nii", "")
mask_operations.export_mask_image_to_disk(mask_name, os.path.join(output_dir, f"{basename}_mask.nii"))
except Exception as e:
print(f" Failed: {e}")
finally:
app.close_project() # free memory before the next file
How do I log batch progress and errors to both a file and the console?
import logging
import ScriptingApi as api
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s [%(levelname)s] %(message)s",
handlers=[
logging.FileHandler("C:/Data/Output/batch.log"),
logging.StreamHandler(),
],
)
logger = logging.getLogger(__name__)
app = api.Application()
volume_operations = app.get_volume_operations()
logger.info("Batch started")
try:
volume_operations.import_3d_image_from_disk("C:/Data/Input/scan.nii")
logger.info("Imported scan.nii")
except Exception as e:
logger.error(f"Import failed: {e}")
How do I read batch parameters from a JSON configuration file?
import json
import ScriptingApi as api
with open("C:/Scripts/batch_config.json", "r") as f:
config = json.load(f)
app = api.Application()
threshold_config = config.get("threshold", {})
params = api.ThresholdParams()
params.lower_threshold = threshold_config.get("lower", 200)
params.upper_threshold = threshold_config.get("upper", 3000)
params.filter_regions = threshold_config.get("filter_regions", True)
# pass params to mask_operations.threshold(volume_name, params)
How do I run TotalSegmentator on many CT scans and export each result as a surface?
Loop over the input files, run TotalSegmentator, convert the masks to surfaces, and export them.
import os
from pathlib import Path
import ScriptingApi as api
app = api.Application()
volume_operations = app.get_volume_operations()
mask_operations = app.get_mask_operations()
surface_operations = app.get_surface_operations()
ai_segmentation = app.get_ai_segmentation()
output_dir = "C:/Data/AI_Results"
os.makedirs(output_dir, exist_ok=True)
files = [str(p) for p in Path("C:/Data/CT_Scans").rglob("*.nii*")]
for filepath in files:
try:
volume_name = volume_operations.import_3d_image_from_disk(filepath)
ai_segmentation.set_model_type(api.AiSegmentationModelType.TotalSegmentator)
ts_params = api.TotalSegmentatorParams()
ts_params.task = "total"
ts_params.device = "gpu"
mask_names = ai_segmentation.run_total_segmentator([volume_name], ts_params)
surfaces = mask_operations.convert_to_surface_objects(mask_names, api.MaskToSurfaceParams())
surface_operations.export_surfaces_to_disk(surfaces, output_dir, "stl", False)
except Exception as e:
print(f"Failed {filepath}: {e}")
finally:
app.close_project()
Data Analysis with NumPy, pandas, and matplotlib
Standard scientific Python libraries can be used inside Volvicon scripts to summarize and visualize results. matplotlib must use a non-interactive backend.
How do I compute summary statistics across many masks with NumPy?
import numpy as np
import ScriptingApi as api
app = api.Application()
measure_operations = app.get_measure_operations()
volumes = app.get_all_volume_names()
masks = app.get_all_mask_names()
volume_values = []
for mask in masks:
stats = measure_operations.compute_whole_mask_statistics(mask, volumes[0], [api.LabelStatisticType.Volume])
volume_values.append(stats.total_volume)
arr = np.array(volume_values)
print(f"Mean: {np.mean(arr):.2f} Std: {np.std(arr):.2f} Max: {np.max(arr):.2f}")
How do I count non-zero voxels in a mask data object?
Mask voxel data is a flat buffer. Use the helper method instead of treating data as nested rows.
import ScriptingApi as api
app = api.Application()
mask_operations = app.get_mask_operations()
masks = app.get_all_mask_names()
if masks:
mask_uint8 = mask_operations.get_mask_uint8(masks[0])
print("Non-zero voxels:", mask_uint8.count_nonzero())
print("Total voxels:", mask_uint8.voxel_count())
Common mistake
# Wrong: mask_uint8.data is a flat buffer, not rows.
voxel_count = 0
for row in mask_uint8.data:
voxel_count += sum(row)
Why it is wrong: Each item in mask_uint8.data is a voxel value, so row is an integer. Use mask_uint8.count_nonzero() for occupied voxels, or iter_rows() when row-shaped iteration is needed.
How do I iterate mask voxel data by rows or slices?
import ScriptingApi as api
app = api.Application()
mask_operations = app.get_mask_operations()
masks = app.get_all_mask_names()
if masks:
mask_uint8 = mask_operations.get_mask_uint8(masks[0])
first_slice_count = 0
for row in mask_uint8.iter_rows(0):
first_slice_count += sum(1 for value in row if value)
slice_count = sum(1 for _slice in mask_uint8.iter_slices())
print("Non-zero voxels in first slice:", first_slice_count)
print("Number of slices:", slice_count)
How do I convert mask voxel data to NumPy and rebuild a mask data object?
import numpy as np
import ScriptingApi as api
app = api.Application()
mask_operations = app.get_mask_operations()
masks = app.get_all_mask_names()
if masks:
mask_uint8 = mask_operations.get_mask_uint8(masks[0])
mask_array = mask_uint8.to_numpy(copy=True) # shape is (depth, height, width)
rebuilt = api.MaskUint8()
rebuilt.update_from_numpy(mask_array.astype(np.uint8))
rebuilt.spacing = list(mask_uint8.spacing)
rebuilt.origin = list(mask_uint8.origin)
# Write back only when you intend to replace compatible mask voxel data:
# mask_operations.set_mask_uint8(masks[0], rebuilt)
print("Array shape:", mask_array.shape)
How do I collect batch results into a pandas DataFrame and export to CSV?
import pandas as pd
import ScriptingApi as api
app = api.Application()
volume_operations = app.get_volume_operations()
records = []
for name in app.get_all_volume_names():
dims = volume_operations.get_dimensions(name)
spacing = volume_operations.get_spacing(name)
records.append({
"volume": name,
"dim_x": dims[0], "dim_y": dims[1], "dim_z": dims[2],
"spacing_x": spacing[0], "spacing_y": spacing[1], "spacing_z": spacing[2],
})
df = pd.DataFrame(records)
print(df.describe())
df.to_csv("C:/Data/Output/volumes.csv", index=False)
How do I create a chart from results with matplotlib inside Volvicon?
Select the non-interactive Agg backend before importing pyplot, and save the figure to a file instead of calling show().
import matplotlib
matplotlib.use("Agg") # non-interactive backend, required inside Volvicon
import matplotlib.pyplot as plt
volumes = [1250.5, 1180.3, 1420.8, 1095.2]
plt.figure(figsize=(8, 5))
plt.bar(range(len(volumes)), volumes, color="steelblue")
plt.xlabel("Dataset")
plt.ylabel("Volume (mm³)")
plt.title("Segmented Volume by Dataset")
plt.savefig("C:/Data/Output/volumes.png", dpi=150, bbox_inches="tight")
plt.close()
How do I export batch statistics to a CSV file using the csv module?
import csv
results = [
{"file": "scan_001", "structure": "liver", "volume_mm3": 1450.2},
{"file": "scan_001", "structure": "spleen", "volume_mm3": 210.7},
]
with open("C:/Data/Output/organ_statistics.csv", "w", newline="") as f:
writer = csv.DictWriter(f, fieldnames=["file", "structure", "volume_mm3"])
writer.writeheader()
writer.writerows(results)
Voxel Data Helper Methods
A mask or volume voxel-data object is retrieved with a typed getter and then carries Python helper methods you call directly on the object (data.to_numpy(), data.count_nonzero(), and so on). Masks use mask_operations.get_mask_uint8(name) (binary / single-label) or get_mask_uint_16(name) (multi-label). Volumes use volume_operations.get_volume_uint8 / get_volume_int_16 / get_volume_uint_16 / get_volume_float_32(name) depending on the stored type. The helpers accept normal Python arguments (including keyword arguments such as to_numpy(copy=True)).
How do I retrieve a mask or volume voxel data object?
Use the typed getter on mask_operations or volume_operations. There is no generic get_mask()/get_volume() — choose the typed getter that matches the stored data.
import ScriptingApi as api
app = api.Application()
mask_operations = app.get_mask_operations()
volume_operations = app.get_volume_operations()
# Binary / single-label masks -> get_mask_uint8 (multi-label -> get_mask_uint_16)
masks = app.get_all_mask_names()
mask_uint8 = mask_operations.get_mask_uint8(masks[0])
print("Mask dimensions (w, h, d):", mask_uint8.voxel_dimensions())
# Volumes -> the getter that matches the type (commonly float32 or int16)
volumes = app.get_all_volume_names()
volume_float32 = volume_operations.get_volume_float_32(volumes[0])
print("Volume dimensions (w, h, d):", volume_float32.voxel_dimensions())
Common mistake
# Wrong: there is no untyped get_mask(name)/get_volume(name), and the
# multi-bit getters carry an underscore before the bit count.
mask_data = app.get_mask("Mask")
Why it is wrong: Retrieve voxel data with a typed getter: get_mask_uint8 / get_mask_uint_16 on mask_operations, and get_volume_uint8 / get_volume_int_16 / get_volume_uint_16 / get_volume_float_32 on volume_operations. There is no untyped get_mask()/get_volume().
How do I read and process volume voxel data as a NumPy array?
import numpy as np
import ScriptingApi as api
app = api.Application()
volume_operations = app.get_volume_operations()
volumes = app.get_all_volume_names()
if volumes:
# Use the getter matching the volume's stored type (float32 shown here).
volume_float_32 = volume_operations.get_volume_float_32(volumes[0])
volume_array = volume_float_32.to_numpy(copy=True) # shape (depth, height, width)
print("Shape:", volume_array.shape)
print("Min/Max:", float(volume_array.min()), float(volume_array.max()))
print("Mean intensity:", float(volume_array.mean()))
What methods and properties are available on a mask or volume voxel data object?
After retrieving the object with a typed getter, these helper methods and properties are available directly on it.
import ScriptingApi as api
app = api.Application()
mask_operations = app.get_mask_operations()
mask_uint8 = mask_operations.get_mask_uint8(app.get_all_mask_names()[0])
# Properties (raw, in-memory data):
# mask_uint8.data flat row-major list of voxel values (X fastest, then Y, then Z)
# mask_uint8.dimensions [width, height, depth]
# mask_uint8.spacing [sx, sy, sz]
# mask_uint8.origin [ox, oy, oz]
#
# Helper methods:
# voxel_dimensions() -> (width, height, depth)
# voxel_count() -> total number of voxels
# count_nonzero() -> number of non-zero voxels
# flat_index(x, y, z=0) -> index into the flat data buffer
# value_at(x, y, z=0) -> voxel value at (x, y, z)
# set_value_at(x, y, z, value) -> set a voxel value (in memory)
# iter_rows(z=None) / rows(z=None) -> iterate / list X rows
# iter_slices() / slices() -> iterate / list Z slices
# to_numpy(copy=False) -> NumPy array, shape (depth, height, width)
# update_from_numpy(array) -> set data + dimensions from a 3D array
print("Dimensions:", mask_uint8.voxel_dimensions())
print("Total voxels:", mask_uint8.voxel_count())
print("Non-zero voxels:", mask_uint8.count_nonzero())
What is mask_data.data and what type is it?
The .data property is a flat, row-major list of individual voxel values — not nested rows and not a NumPy array.
import ScriptingApi as api
app = api.Application()
mask_operations = app.get_mask_operations()
mask_uint8 = mask_operations.get_mask_uint8(app.get_all_mask_names()[0])
width, height, depth = mask_uint8.voxel_dimensions()
# .data is laid out with X fastest, then Y, then Z. Index it via flat_index():
index = mask_uint8.flat_index(0, 0, 0)
print("First voxel value:", mask_uint8.data[index])
# For array math, convert to NumPy (shape is depth, height, width):
mask_array = mask_uint8.to_numpy(copy=True)
print("Array shape:", mask_array.shape)
Common mistake
# Wrong: each item in .data is a single voxel value, not a row.
for row in mask_uint8.data:
process(row) # 'row' is an int, not a list
Why it is wrong: mask_uint8.data is a flat list of voxel values. Use iter_rows()/iter_slices() for shaped iteration, or to_numpy() for a (depth, height, width) array. count_nonzero() and voxel_count() avoid manual iteration entirely.
How do I write modified voxel data back to a mask?
Modify the object in memory (directly, via set_value_at, or via update_from_numpy), then push it back with the matching typed setter.
import numpy as np
import ScriptingApi as api
app = api.Application()
mask_operations = app.get_mask_operations()
masks = app.get_all_mask_names()
if masks:
mask_uint8 = mask_operations.get_mask_uint8(masks[0])
mask_array = mask_uint8.to_numpy(copy=True)
# Example modification: keep only voxels above a label threshold.
cleaned = np.where(mask_array > 0, 1, 0)
rebuilt = api.MaskUint8()
rebuilt.update_from_numpy(cleaned.astype(np.uint8))
rebuilt.spacing = list(mask_uint8.spacing)
rebuilt.origin = list(mask_uint8.origin)
# set_mask_uint8 checks dimension/spacing/origin compatibility before applying.
mask_operations.set_mask_uint8(masks[0], rebuilt)
print("Mask updated.")
Application Preferences
Preferences are read as grouped option objects and changed with individual setters. Get the group with app.get_preferences_operations().
How do I read the current application preferences?
import ScriptingApi as api
app = api.Application()
preferences_operations = app.get_preferences_operations()
ui = preferences_operations.get_user_interface_options()
general = preferences_operations.get_general_options()
print("Show splash screen:", ui.show_splash_screen)
print("Maximum undos:", general.maximum_undos)
How do I change general and interface preferences such as undo count and font size?
import ScriptingApi as api
app = api.Application()
preferences_operations = app.get_preferences_operations()
preferences_operations.set_show_splash_screen(False)
preferences_operations.set_application_font_size(api.ApplicationFontSize.Medium)
preferences_operations.set_maximum_undos(25)
preferences_operations.set_undo_storage_location(api.UndoStorageLocation.Disk)
preferences_operations.set_project_file_compression_level(api.ProjectFileCompressionLevel.Balanced)
How do I configure CAD import defaults such as deflection and solid building?
import ScriptingApi as api
app = api.Application()
preferences_operations = app.get_preferences_operations()
cad_import_options = preferences_operations.get_cad_file_import_options()
cad_import_options.auto_deflections = False
cad_import_options.linear_deflection = 0.01
cad_import_options.angular_deflection = 0.4
cad_import_options.build_solid = True
preferences_operations.set_cad_file_import_options(cad_import_options)
How do I allow importing images with mismatched geometry and resample them?
import ScriptingApi as api
app = api.Application()
preferences_operations = app.get_preferences_operations()
preferences_operations.set_allow_import_of_images_with_mismatched_geometry(True)
preferences_operations.set_resample_mismatched_images_to_match_the_projects_active_volume(True)
preferences_operations.set_volume_interpolation_method_for_mismatched_images(api.ImageInterpolationMethod.Cubic)
preferences_operations.set_mask_interpolation_method_for_mismatched_images(api.ImageInterpolationMethod.Nearest)
Volume Rendering
Volume render properties control shading, blending, slice planes, and bounding boxes for grayscale volumes. Get the group with volume_operations.get_render_properties_operations(). GPU and memory settings live on the view operations group.
How do I enable shading and adjust the lighting of a volume rendering?
import ScriptingApi as api
app = api.Application()
volume_operations = app.get_volume_operations()
volume_render_properties_operations = volume_operations.get_render_properties_operations()
volumes = app.get_all_volume_names()
if volumes:
volume_render_properties_operations.set_shade_enabled([volumes[0]], True)
volume_render_properties_operations.set_ambient_coefficient([volumes[0]], 0.2)
volume_render_properties_operations.set_diffuse_coefficient([volumes[0]], 0.7)
volume_render_properties_operations.set_specular_coefficient([volumes[0]], 0.3)
volume_render_properties_operations.set_specular_power([volumes[0]], 20.0)
How do I set the blend mode and interpolation for a volume rendering?
import ScriptingApi as api
app = api.Application()
volume_operations = app.get_volume_operations()
volume_render_properties_operations = volume_operations.get_render_properties_operations()
volumes = app.get_all_volume_names()
if volumes:
volume_render_properties_operations.set_blend_mode([volumes[0]], 0) # blend mode index
volume_render_properties_operations.set_interpolation([volumes[0]], 1) # interpolation index
How do I show or hide a volume bounding box and its 3D slice planes?
import ScriptingApi as api
app = api.Application()
volume_operations = app.get_volume_operations()
volume_render_properties_operations = volume_operations.get_render_properties_operations()
volumes = app.get_all_volume_names()
if volumes:
volume_render_properties_operations.set_bounding_box_visibility([volumes[0]], True)
volume_render_properties_operations.set_3d_slice_planes_visibility([volumes[0]], True)
How do I restrict a volume rendering to a masked region?
masking shows only the part of the volume covered by the given masks; clear_masking removes the restriction.
import ScriptingApi as api
app = api.Application()
volume_operations = app.get_volume_operations()
volume_render_properties_operations = volume_operations.get_render_properties_operations()
volumes = app.get_all_volume_names()
masks = app.get_all_mask_names()
if volumes and masks:
volume_render_properties_operations.masking(volumes[0], [masks[0]])
# volume_render_properties_operations.clear_masking([volumes[0]]) # remove the restriction
How do I enable GPU volume rendering and set the GPU memory budget?
import ScriptingApi as api
app = api.Application()
view_operations = app.get_view_operations()
view_operations.set_gpu_volume_rendering_enabled(True)
view_operations.set_gpu_memory_budget(api.GpuMemoryBudget.Auto) # or GB4, GB8, GB16, ...
Mask, Surface, and Mesh Rendering
Masks, surfaces, and volume meshes each expose render properties through their operations group via get_render_properties_operations(). Colors are RGB in the 0.0-1.0 range.
How do I set the color, opacity, and representation of a mask in 3D?
import ScriptingApi as api
app = api.Application()
mask_operations = app.get_mask_operations()
mask_render_properties_operations = mask_operations.get_render_properties_operations()
masks = app.get_all_mask_names()
if masks:
mask_render_properties_operations.set_color([masks[0]], [0.8, 0.2, 0.2])
mask_render_properties_operations.set_opacity([masks[0]], 0.8)
mask_render_properties_operations.set_representation([masks[0]], api.SurfaceRepresentation.Solid)
How do I color individual labels of a multi-label mask?
import ScriptingApi as api
app = api.Application()
mask_operations = app.get_mask_operations()
mask_render_properties_operations = mask_operations.get_render_properties_operations()
masks = app.get_all_mask_names()
if masks and mask_operations.is_multilabel_mask(masks[0]):
label_values = mask_operations.get_mask_label_values(masks[0])
mask_render_properties_operations.set_color_to_labels(masks[0], label_values[:1], [0.0, 0.6, 1.0]) # first label blue
mask_render_properties_operations.set_random_colors_to_labels(masks[0], label_values) # random colors for all
How do I give a surface a metallic (PBR) material appearance?
Switch the surface to PBR shading, then set its metallic and roughness coefficients.
import ScriptingApi as api
app = api.Application()
surface_operations = app.get_surface_operations()
surface_render_properties_operations = surface_operations.get_render_properties_operations()
surfaces = app.get_all_surface_names()
if surfaces:
surface_render_properties_operations.set_interpolation([surfaces[0]], api.SurfaceInterpolation.PBR)
surface_render_properties_operations.set_metallic_coefficient([surfaces[0]], 0.9)
surface_render_properties_operations.set_roughness_coefficient([surfaces[0]], 0.3)
How do I get the render-properties operations object (and why does app.get_render_properties_operations fail)?
Render properties live on each object operations group, never on the Application object. Call get_render_properties_operations() on the volume, mask, surface, or volume-mesh operations group.
import ScriptingApi as api
app = api.Application()
# Correct: obtain the render-properties group from each operations group
volume_operations = app.get_volume_operations()
mask_operations = app.get_mask_operations()
surface_operations = app.get_surface_operations()
volume_mesh_operations = app.get_volume_mesh_operations()
volume_render_properties_operations = volume_operations.get_render_properties_operations()
mask_render_properties_operations = mask_operations.get_render_properties_operations()
surface_render_properties_operations = surface_operations.get_render_properties_operations()
volume_mesh_render_properties_operations = volume_mesh_operations.get_render_properties_operations()
surfaces = app.get_all_surface_names()
if surfaces:
surface_render_properties_operations.set_color([surfaces[0]], [1.0, 0.0, 0.0])
Common mistake
# Wrong: the Application object has no render-properties getter.
render = app.get_render_properties_operations() # AttributeError
render = app.get_surface_render_properties_operations() # AttributeError
Why it is wrong: There is no get_render_properties_operations() (or get_surface_render_properties_operations()) on the Application object. Always go through an operations group, for example app.get_surface_operations().get_render_properties_operations().
DICOM Import and Export
DICOM series are discovered in a directory and imported by their instance UID. A volume can be exported back to a DICOM series, an image stack, or have its metadata tags inspected.
How do I import a DICOM series chosen by its description?
List the series in the directory, pick one by description, then import it by its instance UID.
import ScriptingApi as api
app = api.Application()
volume_operations = app.get_volume_operations()
options = api.DicomSeriesImportOptions()
series = volume_operations.get_dicom_series_in_directory("C:/data/dicom", options)
for s in series:
print(s.series_index, s.series_description, s.series_instance_uid)
chosen = [s for s in series if "CHEST" in s.series_description.upper()]
if chosen:
volume_name = volume_operations.import_dicom_series_from_directory(
"C:/data/dicom", [chosen[0].series_instance_uid], options
)
print("Imported:", volume_name)
How do I export a volume as a DICOM series?
import ScriptingApi as api
app = api.Application()
volume_operations = app.get_volume_operations()
volumes = app.get_all_volume_names()
if volumes:
volume_operations.export_volume_image_as_dicom_series(
volumes[0], "C:/output/dicom", "IMG" # volume, output directory, file name prefix
)
How do I read DICOM metadata tags from a volume?
import ScriptingApi as api
app = api.Application()
volume_operations = app.get_volume_operations()
volumes = app.get_all_volume_names()
if volumes:
keys = volume_operations.get_meta_data_keys(volumes[0])
print("Metadata keys:", len(keys))
if keys:
tag = volume_operations.get_meta_data(volumes[0], keys[0])
print(keys[0], "=", tag.value)
How do I export a volume as a stack of PNG slice images?
import ScriptingApi as api
app = api.Application()
volume_operations = app.get_volume_operations()
volumes = app.get_all_volume_names()
if volumes:
volume_operations.export_volume_image_as_image_stack(
volumes[0],
"C:/output/stack", # output directory
"Slice", # file name prefix
"png", # file extension
api.SlicePlane.XY # slice plane
)
Medical and Life-Science Use Cases
Worked examples for common medical and life-science tasks. Volvicon is intended for research and non-clinical use.
How do I segment bone from a CT scan and export a watertight STL for 3D printing?
Threshold the bone range, keep the largest region, build a surface, repair it, then export.
import ScriptingApi as api
app = api.Application()
mask_operations = app.get_mask_operations()
surface_operations = app.get_surface_operations()
volume_name = app.get_active_volume_name()
threshold_params = api.ThresholdParams()
threshold_params.lower_threshold = 200
threshold_params.upper_threshold = 3000
threshold_params.filter_regions = True
threshold_params.keep_largest = True
mask_name = mask_operations.threshold(volume_name, threshold_params)
surface_params = api.MaskToSurfaceParams()
surface_params.smoothing = True
surface_params.smooth_iterations = 30
surfaces = mask_operations.convert_to_surface_objects([mask_name], surface_params)
# Repair to make watertight, then export
surface_operations.fix_surface(surfaces[0], api.SurfaceDiagnosticsChecks())
surface_operations.export_surface_to_disk(surfaces[0], "C:/output/bone.stl", False)
How do I segment the liver with TotalSegmentator and measure its volume?
Run TotalSegmentator, then read the volume of the liver label from the result.
import ScriptingApi as api
app = api.Application()
ai_segmentation = app.get_ai_segmentation()
measure_operations = app.get_measure_operations()
volume_name = app.get_active_volume_name()
ai_segmentation.set_model_type(api.AiSegmentationModelType.TotalSegmentator)
params = ai_segmentation.get_default_total_segmentator_params()
params.task = "total"
params.device = "gpu"
masks = ai_segmentation.run_total_segmentator([volume_name], params)
for mask_name in masks:
if "liver" in mask_name.lower():
stats = measure_operations.compute_whole_mask_statistics(mask_name, volume_name, [api.LabelStatisticType.Volume])
print("Liver volume (mm³):", stats.total_volume)
How do I compare an AI segmentation against a manual one using the Dice coefficient?
import ScriptingApi as api
app = api.Application()
measure_operations = app.get_measure_operations()
masks = app.get_all_mask_names()
if len(masks) >= 2:
comparison = measure_operations.compare_masks(masks[0], masks[1]) # source, target
print("Dice:", comparison.dice_coefficient)
print("False negative:", comparison.false_negative, "False positive:", comparison.false_positive)
How do I rigidly register an MRI volume to a CT volume (multi-modal alignment)?
import ScriptingApi as api
app = api.Application()
registration_operations = app.get_registration_operations()
volumes = app.get_all_volume_names()
if len(volumes) >= 2:
moving = api.GlobalRegistrationObject()
moving.name = volumes[0] # MRI
moving.type = api.GlobalRegistrationObjectType.Volume
fixed = api.GlobalRegistrationObject()
fixed.name = volumes[1] # CT
fixed.type = api.GlobalRegistrationObjectType.Volume
image_params = api.ImageRegistrationParams()
image_params.algorithm = api.GlobalRegistrationImageAlgorithm.Rigid6DOF
image_params.number_of_iterations = 100
result = registration_operations.global_registration(
[moving], fixed, api.SurfaceRegistrationParams(), image_params, True
)
print("Aligned:", result.success, "RMSE:", result.rmse_millimeters)
How do I reduce metal artifacts in a CT scan of an implant?
import ScriptingApi as api
app = api.Application()
volume_operations = app.get_volume_operations()
volume_name = app.get_active_volume_name()
if volume_name:
volume_operations.metal_artifact_reduction_filter(
[volume_name],
3000.0, # metal threshold
1.5 # inpaint sigma
)
How do I measure the distance between two anatomical landmarks?
import ScriptingApi as api
app = api.Application()
measurement_operations = app.get_measurement_operations()
distance = measurement_operations.create_distance(
[45.3, 67.8, 123.4], # landmark A (world mm)
[89.1, 102.5, 145.9], # landmark B (world mm)
"Landmark A-B"
)
result = measurement_operations.get_distance_measurement(distance)
print("Distance:", result.distance, "mm")
How do I reslice a volume along an oblique plane (multi-planar reformat)?
import ScriptingApi as api
app = api.Application()
volume_operations = app.get_volume_operations()
volume_name = app.get_active_volume_name()
if volume_name:
volume_operations.reslice(
[volume_name],
[0.0, 0.0, 0.0], # plane origin (world mm)
[1.0, 1.0, 0.0], # plane normal
api.Interpolation.Linear, # volume interpolation
api.Interpolation.Nearest # mask interpolation
)
How do I create a hollow, printable anatomical model from a segmentation mask?
Build a surface from the mask, repair it, hollow it to a wall thickness, then export.
import ScriptingApi as api
app = api.Application()
mask_operations = app.get_mask_operations()
surface_operations = app.get_surface_operations()
mask_name = app.get_active_mask_name()
surface_params = api.MaskToSurfaceParams()
surface_params.smoothing = True
surface_params.smooth_iterations = 30
surfaces = mask_operations.convert_to_surface_objects([mask_name], surface_params)
surface_operations.fix_surface(surfaces[0], api.SurfaceDiagnosticsChecks())
hollowed = surface_operations.hollow(
[surfaces[0]],
api.SurfaceHollowMethod.Fast,
api.SurfaceHollowDirection.Inward,
2.0, # wall thickness (mm)
api.SurfaceHollowResolution.Medium,
True # create a new surface
)
surface_operations.export_surface_to_disk(hollowed[0], "C:/output/hollow_model.stl", False)
How do I quantify a segmented lesion volume and its bounding box?
import ScriptingApi as api
app = api.Application()
measure_operations = app.get_measure_operations()
mask_name = app.get_active_mask_name()
volume_name = app.get_active_volume_name()
if mask_name and volume_name:
requested = [
api.LabelStatisticType.Volume,
api.LabelStatisticType.VoxelCount,
api.LabelStatisticType.BoundingBox,
]
stats = measure_operations.compute_whole_mask_statistics(mask_name, volume_name, requested)
print("Volume (mm³):", stats.total_volume, "Voxels:", stats.total_voxel_count)
How do I mirror the healthy side of an anatomy to reconstruct a defect (craniomaxillofacial planning)?
Duplicate the intact contralateral surface so the original is preserved, then mirror the copy across the patient mid-sagittal plane to build a reconstruction template for the defective side.
import ScriptingApi as api
app = api.Application()
surface_operations = app.get_surface_operations()
# Start from the intact (healthy) side surface
intact = app.get_active_surface_name()
# Duplicate, then mirror the copy across the mid-sagittal plane
copies = app.duplicate_surfaces([intact])
template = copies[0]
# Plane through the midline (origin on the midline, normal along X)
surface_operations.mirror_to_plane([template], [0.0, 0.0, 0.0], [1.0, 0.0, 0.0])
app.rename_surface(template, "Reconstruction_Template")
Result: The mirrored copy overlays the contralateral defect and serves as a patient-specific reconstruction template for an implant or graft. Set the plane origin and normal to the actual patient mid-sagittal plane.
How do I measure how close a tumor is to a nearby blood vessel (oncology planning)?
Run a signed deviation analysis of the tumor mask against the vessel surface; the minimum distance is the closest approach between them.
import ScriptingApi as api
app = api.Application()
analysis_operations = app.get_analysis_operations()
tumor_mask = app.get_active_mask_name()
surfaces = app.get_all_surface_names()
if tumor_mask and surfaces:
vessel_surface = surfaces[0]
params = api.DeviationParams()
params.method = api.DeviationMethod.Signed
name = analysis_operations.create_deviation_analysis_mask_vs_surface(
"TumorToVessel", tumor_mask, vessel_surface, params
)
analysis_operations.run_analysis(name)
results = analysis_operations.get_deviation_analysis_results(name)
print("Closest approach (mm):", results.statistics.min_value)
print("Mean distance (mm):", results.statistics.mean_value)
Industrial and NDT Use Cases
Worked examples for non-destructive testing, dimensional metrology, and additive manufacturing.
How do I inspect a cast part for porosity and report the porosity value?
import ScriptingApi as api
app = api.Application()
analysis_operations = app.get_analysis_operations()
volume_name = app.get_active_volume_name()
params = api.VoidInclusionParams()
params.mode = api.VoidInclusionTargetType.Void
params.method = api.VoidInclusionMethod.Absolute
params.auto_absolute_contrast = True
name = analysis_operations.create_void_inclusion_analysis("Porosity_1", volume_name, "", params)
analysis_operations.run_analysis(name)
results = analysis_operations.get_void_inclusion_results(name)
print("Defects:", results.total_defects_found, "Porosity:", results.porosity)
analysis_operations.write_void_inclusion_results_to_disk(results, "C:/output/porosity.txt")
How do I detect bright inclusions (dense particles) in a material scan?
Set the analysis mode to Inclusion to detect high-density features instead of dark voids.
import ScriptingApi as api
app = api.Application()
analysis_operations = app.get_analysis_operations()
volume_name = app.get_active_volume_name()
params = api.VoidInclusionParams()
params.mode = api.VoidInclusionTargetType.Inclusion
params.method = api.VoidInclusionMethod.Absolute
params.auto_absolute_contrast = True
name = analysis_operations.create_void_inclusion_analysis("Inclusions_1", volume_name, "", params)
analysis_operations.run_analysis(name)
results = analysis_operations.get_void_inclusion_results(name)
print("Inclusions found:", results.total_defects_found)
How do I compare a scanned surface to a reference CAD model (nominal/actual deviation)?
Import the CAD reference, run a surface-vs-surface deviation analysis, then read and export the result.
import ScriptingApi as api
app = api.Application()
surface_operations = app.get_surface_operations()
analysis_operations = app.get_analysis_operations()
scanned = app.get_active_surface_name()
reference = surface_operations.import_surface_from_disk("C:/data/nominal.stl")
params = api.DeviationParams()
params.method = api.DeviationMethod.Signed
name = analysis_operations.create_deviation_analysis_surface_vs_surface("Deviation_1", scanned, reference, params)
analysis_operations.run_analysis(name)
results = analysis_operations.get_deviation_analysis_results(name)
print("Mean deviation:", results.statistics.mean_value)
analysis_operations.write_deviation_results_to_disk(results, "C:/output/deviation.txt")
How do I measure the distance between two fitted features (dimensional metrology)?
Fit a primitive to each surface feature, then measure between the fitted primitives.
import ScriptingApi as api
app = api.Application()
measure_operations = app.get_measure_operations()
surfaces = app.get_all_surface_names()
if len(surfaces) >= 2:
params = api.PrimitiveFittingParams()
params.primitive_type = api.PrimitiveFittingType.Sphere
params.source = api.PrimitiveFittingSource.Surface
fit_a = measure_operations.fit_primitive_to_surface(surfaces[0], params)
fit_b = measure_operations.fit_primitive_to_surface(surfaces[1], params)
measurement = measure_operations.measure_between_primitives(fit_a.primitive_name, fit_b.primitive_name, True)
print("Distance between features:", measurement.distance)
How do I prepare a scanned part for 3D printing (repair, reduce, export 3MF)?
import ScriptingApi as api
app = api.Application()
surface_operations = app.get_surface_operations()
surfaces = app.get_all_surface_names()
if surfaces:
surface = surfaces[0]
surface_operations.fix_surface(surface, api.SurfaceDiagnosticsChecks()) # make watertight
surface_operations.reduce([surface], 50.0, True, 0) # reduce to 50%
surface_operations.export_surface_to_disk(surface, "C:/output/part.3mf", False)
How do I turn an imported CAD surface into a meshed FEA model and export it to Abaqus?
Import the CAD surface, convert it to a tetrahedral volume mesh, build an FEM model with a material, then export.
import ScriptingApi as api
app = api.Application()
surface_operations = app.get_surface_operations()
volume_mesh_operations = app.get_volume_mesh_operations()
fem_operations = volume_mesh_operations.get_fem_operations()
surface = surface_operations.import_surface_from_disk("C:/data/part.step")
mesh_params = api.VolumeMeshParams()
mesh_params.resolution = api.VolumeMeshResolution.Moderate
surface_operations.set_volume_mesh_parameters(surface, mesh_params)
meshes = surface_operations.convert_to_volume_mesh([surface], api.VolumeMeshMethod.Auto3D)
mesh = meshes[0]
fem_operations.create_fem_model(mesh)
fem_operations.add_material_from_preset(mesh, api.FemMaterialPreset.Steel, "Steel")
common = api.FemExportOptions()
common.model_name = "PartModel"
abaqus = api.FemAbaqusExportOptions()
abaqus.common = common
result = fem_operations.export_to_abaqus(mesh, "C:/output/part.inp", abaqus)
print("Export success:", result.success)
How do I check tetrahedral mesh quality before running an FEA solve?
import ScriptingApi as api
app = api.Application()
measure_operations = app.get_measure_operations()
meshes = app.get_all_volume_mesh_names()
if meshes:
quality = measure_operations.analyze_volume_mesh_quality(meshes[0], api.VolumeMeshQualityMetric.TetAspectRatio)
print("Mean aspect ratio:", quality.statistics.mean_value)
How do I define a custom FEM material with specific mechanical properties?
import ScriptingApi as api
app = api.Application()
volume_mesh_operations = app.get_volume_mesh_operations()
fem_operations = volume_mesh_operations.get_fem_operations()
meshes = app.get_all_volume_mesh_names()
if meshes:
mechanical = api.FemMechanicalProperties()
mechanical.youngs_modulus = 210.0e9 # Pa
mechanical.poissons_ratio = 0.3
material = api.FemMaterialParams()
material.name = "CustomSteel"
material.model = api.FemMaterialModel.Elastic
material.density = 7850.0 # kg/m³
material.mechanical = mechanical
fem_operations.create_fem_model(meshes[0])
fem_operations.add_material(meshes[0], material)
How do I verify a model is watertight before 3D printing?
Run surface diagnostics and inspect holes, self-intersections, and non-manifold edges; repair if any are found.
import ScriptingApi as api
app = api.Application()
surface_operations = app.get_surface_operations()
surfaces = app.get_all_surface_names()
if surfaces:
checks = api.SurfaceDiagnosticsChecks()
result = surface_operations.diagnose_surface(surfaces[0], checks)
print("Holes:", result.holes)
print("Self-intersections:", result.intersection_triangles)
print("Non-manifold edges:", result.non_manifold_edges)
if result.holes or result.intersection_triangles or result.non_manifold_edges:
surface_operations.fix_surface(surfaces[0], checks)
FEA Model Preparation
After creating an FEM model on a volume mesh, define node sets, element sets, and boundary surfaces, then export to a solver. Get the group with volume_mesh_operations.get_fem_operations().
How do I create a node set from explicit node IDs for a boundary condition?
import ScriptingApi as api
app = api.Application()
volume_mesh_operations = app.get_volume_mesh_operations()
fem_operations = volume_mesh_operations.get_fem_operations()
meshes = app.get_all_volume_mesh_names()
if meshes:
params = api.FemNodeSetParams()
params.name = "FixedNodes"
params.node_ids = [1, 2, 3, 4, 5] # 1-based node IDs
params.source = api.FemSetSource.Manual
fem_operations.create_node_set(meshes[0], params)
How do I create a node set from an ROI primitive?
Place an ROI primitive (box, sphere, ...) in the scene, then select the nodes inside it.
import ScriptingApi as api
app = api.Application()
volume_mesh_operations = app.get_volume_mesh_operations()
fem_operations = volume_mesh_operations.get_fem_operations()
meshes = app.get_all_volume_mesh_names()
if meshes:
fem_operations.create_node_set_from_roi(meshes[0], "BoxPrimitive", "ROI_FixedNodes")
How do I create an element set from explicit element IDs?
import ScriptingApi as api
app = api.Application()
volume_mesh_operations = app.get_volume_mesh_operations()
fem_operations = volume_mesh_operations.get_fem_operations()
meshes = app.get_all_volume_mesh_names()
if meshes:
params = api.FemElementSetParams()
params.name = "CoreElements"
params.element_ids = [1, 2, 3, 10, 11] # 1-based element IDs
params.source = api.FemSetSource.Manual
fem_operations.create_element_set(meshes[0], params)
How do I detect the external boundary surfaces of a volume mesh for FEA?
import ScriptingApi as api
app = api.Application()
volume_mesh_operations = app.get_volume_mesh_operations()
fem_operations = volume_mesh_operations.get_fem_operations()
meshes = app.get_all_volume_mesh_names()
if meshes:
fem_operations.detect_boundary_surfaces(meshes[0], "ExternalBoundary")
How do I create an FEM part from an element set and assign a material?
import ScriptingApi as api
app = api.Application()
volume_mesh_operations = app.get_volume_mesh_operations()
fem_operations = volume_mesh_operations.get_fem_operations()
meshes = app.get_all_volume_mesh_names()
if meshes:
fem_operations.create_part_from_element_set(meshes[0], "CoreElements", "CorePart", "Steel")
How do I create node and element sets from all visible ROI primitives at once?
import ScriptingApi as api
app = api.Application()
volume_mesh_operations = app.get_volume_mesh_operations()
fem_operations = volume_mesh_operations.get_fem_operations()
meshes = app.get_all_volume_mesh_names()
if meshes:
fem_operations.create_sets_from_visible_roi(meshes[0], "ROI_Nodes", "ROI_Elements")
How do I show node sets, element sets, and boundary surfaces in the 3D view?
import ScriptingApi as api
app = api.Application()
volume_mesh_operations = app.get_volume_mesh_operations()
fem_operations = volume_mesh_operations.get_fem_operations()
meshes = app.get_all_volume_mesh_names()
if meshes:
fem_operations.show_node_sets(meshes[0], [], True) # empty list = show all
fem_operations.show_element_sets(meshes[0], [], True)
fem_operations.show_surfaces(meshes[0], [], True)
How do I export an FEM model to Nastran or LS-DYNA?
Each solver has a typed options object, or use export_to_format with a format selector.
import ScriptingApi as api
app = api.Application()
volume_mesh_operations = app.get_volume_mesh_operations()
fem_operations = volume_mesh_operations.get_fem_operations()
meshes = app.get_all_volume_mesh_names()
if meshes:
common = api.FemExportOptions()
common.model_name = "Model"
nastran = api.FemNastranExportOptions()
nastran.common = common
fem_operations.export_to_nastran(meshes[0], "C:/output/model.nas", nastran)
# Generic exporter with a format selector
fem_operations.export_to_format(meshes[0], "C:/output/model.k", api.FemExportFormat.LSDYNA, common)
How do I export a volume mesh as an OpenFOAM CFD case?
import ScriptingApi as api
app = api.Application()
volume_mesh_operations = app.get_volume_mesh_operations()
fem_operations = volume_mesh_operations.get_fem_operations()
meshes = app.get_all_volume_mesh_names()
if meshes:
common = api.FemExportOptions()
common.model_name = "case"
openfoam = api.FemOpenFOAMExportOptions()
openfoam.common = common
openfoam.create_case_structure = True
result = fem_operations.export_to_open_foam(meshes[0], "C:/output/openfoam_case", openfoam)
print("Export success:", result.success)
End-to-End Workflows
These examples combine several operations into a complete task. Keep paths and object names appropriate to your project.
How do I segment by threshold, build a surface, and export it as STL?
import ScriptingApi as api
app = api.Application()
mask_operations = app.get_mask_operations()
surface_operations = app.get_surface_operations()
volume_name = app.get_active_volume_name()
threshold_params = api.ThresholdParams()
threshold_params.lower_threshold = 200
threshold_params.upper_threshold = 3000
threshold_params.filter_regions = True
threshold_params.keep_largest = True
mask_name = mask_operations.threshold(volume_name, threshold_params)
surface_params = api.MaskToSurfaceParams()
surface_params.smoothing = True
surface_params.smooth_iterations = 30
surfaces = mask_operations.convert_to_surface_objects([mask_name], surface_params)
surface_operations.remesh(surfaces)
surface_operations.export_surface_to_disk(surfaces[0], "C:/output/model.stl", False)
Result: Produces a cleaned surface from a threshold segmentation and writes it to disk.
How do I batch-export every surface in the project to a folder?
import ScriptingApi as api
app = api.Application()
surface_operations = app.get_surface_operations()
surfaces = app.get_all_surface_names()
if surfaces:
surface_operations.export_surfaces_to_disk(surfaces, "C:/output/surfaces", "stl", False)
How do I run a complete wall-thickness analysis from a volume to results on disk?
Threshold the active volume, build and clean a surface, run the analysis, then read and export the results.
import ScriptingApi as api
app = api.Application()
mask_operations = app.get_mask_operations()
surface_operations = app.get_surface_operations()
analysis_operations = app.get_analysis_operations()
volume_name = app.get_active_volume_name()
threshold_params = api.ThresholdParams()
threshold_params.lower_threshold = 200
threshold_params.upper_threshold = 3000
threshold_params.fill_cavities = True
threshold_params.filter_regions = True
threshold_params.keep_largest = True
mask_name = mask_operations.threshold(volume_name, threshold_params)
surface_params = api.MaskToSurfaceParams()
surface_params.smoothing = True
surface_params.smooth_iterations = 50
surfaces = mask_operations.convert_to_surface_objects([mask_name], surface_params)
surface_operations.remesh(surfaces)
surface_operations.fix_surface(surfaces[0], api.SurfaceDiagnosticsChecks())
wt_params = api.WallThicknessParams()
wt_params.method = api.WallThicknessMethod.RayCasting
wt_params.max_wall_thickness = 20.0
wt_params.search_angle = 20.0
wt_name = analysis_operations.create_wall_thickness_analysis_surface("WallThickness_1", surfaces[0], wt_params)
analysis_operations.run_analysis(wt_name)
results = analysis_operations.get_wall_thickness_analysis_results(wt_name)
print("Mean wall thickness:", results.statistics.mean_value)
analysis_operations.write_wall_thickness_results_to_disk(results, "C:/output/wall_thickness.txt")
How do I finish a workflow by saving snapshots and the project, then freeing memory?
import ScriptingApi as api
app = api.Application()
app.save_snapshot_to_disk(api.SnapshotType.Application, "C:/output/application.png")
app.save_snapshot_to_disk(api.SnapshotType.Scene, "C:/output/scene.png")
app.save_snapshot_to_disk(api.SnapshotType.View3D, "C:/output/view3d.png")
app.save_project("C:/output/workflow.vvcx")
app.close_project() # close to free memory
Related Resources
- API Reference - Full class and method reference
- Quick Reference - Common methods at a glance
- Scripting API Code Examples - Downloadable tutorial scripts