Measure Operations
Measure Operations Tutorial.
This tutorial demonstrates the Measure Operations scripting API for computing histograms, statistics, mesh quality metrics, primitive fitting, and distance measurements. Each section provides a workflow example and prints results.
Note: The UI measure tools rely on interactive input (picking points, charts). Those interactions are not available via scripting. For interactive analysis, use the Measure tab in the UI. This tutorial focuses on scripting equivalents.
Prerequisites
- Volvicon application must be running
- Relevant objects loaded (volumes, masks, surfaces, and meshes as required)
Histogram Operations​
if all_volumes:
volume_name = all_volumes[0]
histogram_params = api.HistogramParams()
histogram_params.target = api.VolumeStatisticsTarget.WholeVolume
histogram_params.slice_mode = api.SliceMode.AllSlices
histogram_params.y_axis_mode = api.HistogramYAxisMode.Linear
histogram_params.graph_type = api.HistogramGraphType.Bar
histogram_params.number_of_bins = 64
histogram : api.HistogramResult = measure_operations.generate_histogram(volume_name, histogram_params)
print(f"Histogram volume: {histogram.volume_name}")
print(f"Histogram bin count: {len(histogram.bin_values)}")
print(f"Histogram total count: {histogram.total_count}")
if histogram.bin_values:
print(f"Histogram first bin: {histogram.bin_values[0]}, freq: {histogram.frequencies[0]}")
histogram_txt = r"C:\output\histogram.txt"
measure_operations.export_histogram_to_disk(histogram, histogram_txt)
if all_masks:
mask_name = all_masks[0]
histogram_with_mask : api.HistogramResult = measure_operations.generate_histogram_with_mask(volume_name, mask_name, histogram_params)
print(f"Histogram with mask: {histogram_with_mask.mask_name}")
# number_of_bins, target, and slice_mode control how the histogram data is computed.
# Setting image_file_path also saves a styled histogram chart image to disk; in that case
# graph_type selects the chart style and y_axis_mode selects the exported image Y-axis scaling.
histogram_image_params = api.HistogramParams()
histogram_image_params.target = api.VolumeStatisticsTarget.VisibleMasks
histogram_image_params.slice_mode = api.SliceMode.CurrentSliceZ
histogram_image_params.y_axis_mode = api.HistogramYAxisMode.Logarithmic
histogram_image_params.graph_type = api.HistogramGraphType.Bar
histogram_image_params.number_of_bins = 256
# Saving the generated histogram image to disk.
histogram_image_params.image_file_path = r"C:\output\histogram.png"
measure_operations.generate_histogram(volume_name, histogram_image_params)
print(f"Histogram image saved to: {histogram_image_params.image_file_path}")
Volume Statistics Operations​
if all_volumes:
volume_name = all_volumes[0]
volume_statistics_params = api.VolumeStatisticsParams()
volume_statistics_params.target = api.VolumeStatisticsTarget.WholeVolume
volume_statistics_params.slice_mode = api.SliceMode.AllSlices
volume_statistics_params.histogram_bins = 128
volume_stats : api.VolumeStatisticsResult = measure_operations.compute_volume_statistics(volume_name, volume_statistics_params)
print(f"Volume stats: {volume_stats.volume_name}")
print(f" Mean intensity: {volume_stats.mean_intensity}")
print(f" Std dev: {volume_stats.standard_deviation}")
print(f" Voxel count: {volume_stats.voxel_count}")
volume_stats_txt = r"C:\output\volume_statistics.txt"
measure_operations.export_volume_statistics_to_disk(volume_stats, volume_stats_txt)
if all_masks:
mask_name = all_masks[0]
stats_with_mask : api.VolumeStatisticsResult = measure_operations.compute_volume_statistics_with_mask(volume_name, mask_name, volume_statistics_params)
print(f"Volume stats with mask: {stats_with_mask.mask_name}")
print(f" Mean intensity: {stats_with_mask.mean_intensity}")
# Compute statistics for the volume restricted to each currently visible mask.
visible_mask_names = app.get_visible_mask_names()
print(f"Visible mask count: {len(visible_mask_names)}")
for visible_mask_name in visible_mask_names:
visible_volume_stats : api.VolumeStatisticsResult = measure_operations.compute_volume_statistics_with_mask(volume_name, visible_mask_name, volume_statistics_params)
print(f" Mask {visible_volume_stats.mask_name}: mean={visible_volume_stats.mean_intensity}")
Volume Similarity Statistics​
if all_volumes:
source_volume = all_volumes[0]
target_volume = all_volumes[1] if len(all_volumes) > 1 else ""
if not target_volume:
duplicated = app.duplicate_volumes([source_volume])
if duplicated:
target_volume = duplicated[0]
if target_volume:
similarity : api.VolumeSimilarityResult = measure_operations.compute_volume_similarity(source_volume, target_volume)
print(f"Volume similarity: {similarity.source_volume_name} vs {similarity.target_volume_name}")
print(f" CC: {similarity.cross_correlation}")
print(f" MI: {similarity.mutual_information}")
similarity_txt = r"C:\output\volume_similarity.txt"
measure_operations.export_volume_similarity_to_disk(similarity, similarity_txt)
Mask Statistics Operations​
if all_masks:
mask_name = all_masks[0]
volume_name = all_volumes[0] if all_volumes else ""
requested_label_stats = [
api.LabelStatisticType.VoxelCount,
api.LabelStatisticType.Volume,
api.LabelStatisticType.MeanIntensity
]
whole_mask_stats : api.MaskStatisticsResult = measure_operations.compute_whole_mask_statistics(mask_name, volume_name, requested_label_stats)
print(f"Whole mask stats: {whole_mask_stats.mask_name}")
print(f" Total regions: {whole_mask_stats.total_regions}")
print(f" Total voxel count: {whole_mask_stats.total_voxel_count}")
for stats in whole_mask_stats.label_statistics:
mask_label_stats : api.MaskLabelStatistics = stats
print(f" Label {mask_label_stats.label}: volume={mask_label_stats.volume}")
per_region_stats : api.MaskStatisticsResult = measure_operations.compute_per_region_mask_statistics(mask_name, volume_name, requested_label_stats)
print(f"Per-region stats count: {len(per_region_stats.label_statistics)}")
for stats in per_region_stats.label_statistics:
region_stats : api.MaskLabelStatistics = stats
print(f" Region {region_stats.label}: voxels={region_stats.voxel_count}")
if mask_operations.is_multilabel_mask(mask_name):
per_label_stats : api.MaskStatisticsResult = measure_operations.compute_per_label_mask_statistics(mask_name, volume_name, requested_label_stats)
print(f"Per-label stats count: {len(per_label_stats.label_statistics)}")
for stats in per_label_stats.label_statistics:
mask_label_stats : api.MaskLabelStatistics = stats
print(f" Label {mask_label_stats.label}: volume={mask_label_stats.volume}")
else:
print("Mask is not multi-label; skipping per-label statistics.")
mask_stats_txt = r"C:\output\mask_statistics.txt"
measure_operations.export_mask_statistics_to_disk(whole_mask_stats, mask_stats_txt)
Compare Masks​
if len(all_masks) >= 2:
mask_a = all_masks[0]
mask_b = all_masks[1]
comparison : api.MaskComparisonResult = measure_operations.compare_masks(mask_a, mask_b)
print(f"Mask comparison: {comparison.source_mask_name} vs {comparison.target_mask_name}")
print(f" Dice coefficient: {comparison.dice_coefficient}")
print(f" False negative: {comparison.false_negative}")
print(f" False positive: {comparison.false_positive}")
for stats in comparison.label_statistics:
label_comparison : api.MaskComparisonLabelStatistics = stats
print(f" Label {label_comparison.label}: dice={label_comparison.dice_coefficient}")
comparison_txt = r"C:\output\mask_comparison.txt"
measure_operations.export_mask_comparison_to_disk(comparison, comparison_txt)
Mask 3D Preview Statistics and Quality​
if all_masks:
mask_name = all_masks[0]
app.set_mask_3d_preview_quality(api.Mask3dPreviewQuality.Optimal)
app.generate_mask_3d_preview([mask_name])
requested_mesh_stats = [
api.SurfaceMeshStatisticType.NumVertices,
api.SurfaceMeshStatisticType.SurfaceArea
]
preview_stats : api.SurfaceMeshStatisticsResult = measure_operations.compute_per_region_mask_3d_preview_statistics(mask_name, requested_mesh_stats)
print(f"Mask 3D preview regions: {len(preview_stats.statistics)}")
if preview_stats.statistics:
stats0 : api.SurfaceMeshStatistics = preview_stats.statistics[0]
print(f" Region {stats0.region_id}: vertices={stats0.num_vertices}, area={stats0.surface_area}")
if mask_operations.is_multilabel_mask(mask_name):
preview_label_stats : api.SurfaceMeshStatisticsResult = measure_operations.compute_per_label_mask_3d_preview_statistics(mask_name, requested_mesh_stats)
print(f"Mask 3D preview labels: {len(preview_label_stats.statistics)}")
for stats in preview_label_stats.statistics:
label_mesh_stats : api.SurfaceMeshStatistics = stats
print(f" Label {label_mesh_stats.region_id}: vertices={label_mesh_stats.num_vertices}")
preview_quality : api.SurfaceMeshQualityResult = measure_operations.analyze_mask_3d_preview_mesh_quality(mask_name, api.SurfaceMeshQualityMetric.AspectRatio)
print(f"Mask 3D preview quality: {preview_quality.surface_name}")
preview_quality_stats : api.QualityMetricStatistics = preview_quality.statistics
print(f" Min: {preview_quality_stats.min_value}")
Surface Mesh Statistics and Quality​
if all_surfaces:
surface_name = all_surfaces[0]
requested_mesh_stats = [
api.SurfaceMeshStatisticType.NumVertices,
api.SurfaceMeshStatisticType.SurfaceArea
]
surface_stats : api.SurfaceMeshStatisticsResult = measure_operations.compute_whole_surface_mesh_statistics(surface_name, requested_mesh_stats)
print(f"Surface stats: {surface_stats.surface_name}")
if surface_stats.statistics:
stats0 : api.SurfaceMeshStatistics = surface_stats.statistics[0]
print(f" Vertices: {stats0.num_vertices}")
print(f" Surface area: {stats0.surface_area}")
visible_surface_stats = measure_operations.compute_all_visible_surface_mesh_statistics(requested_mesh_stats)
print(f"Visible surface stats count: {len(visible_surface_stats)}")
for result in visible_surface_stats:
visible_surface_stats_result : api.SurfaceMeshStatisticsResult = result
print(f" Surface: {visible_surface_stats_result.surface_name}")
per_region_surface_stats : api.SurfaceMeshStatisticsResult = measure_operations.compute_per_region_surface_mesh_statistics(surface_name, requested_mesh_stats)
print(f"Surface regions: {len(per_region_surface_stats.statistics)}")
for stats in per_region_surface_stats.statistics:
region_surface_stats : api.SurfaceMeshStatistics = stats
print(f" Region {region_surface_stats.region_id}: area={region_surface_stats.surface_area}")
surface_stats_txt = r"C:\output\surface_statistics.txt"
measure_operations.export_surface_mesh_statistics_to_disk(surface_stats, surface_stats_txt)
surface_quality : api.SurfaceMeshQualityResult = measure_operations.analyze_surface_mesh_quality(surface_name, api.SurfaceMeshQualityMetric.AspectRatio)
print(f"Surface quality: {surface_quality.surface_name}")
surface_quality_stats : api.QualityMetricStatistics = surface_quality.statistics
print(f" Mean: {surface_quality_stats.mean_value}")
surface_quality_txt = r"C:\output\surface_quality.txt"
measure_operations.export_surface_mesh_quality_to_disk(surface_quality, surface_quality_txt)
Volume Mesh Statistics and Quality​
if all_volume_meshes:
volume_mesh_name = all_volume_meshes[0]
requested_volume_mesh_stats = [
api.VolumeMeshStatisticType.NumVertices,
api.VolumeMeshStatisticType.TotalVolume
]
volume_mesh_stats : api.VolumeMeshStatisticsResult = measure_operations.compute_volume_mesh_statistics(volume_mesh_name, requested_volume_mesh_stats)
print(f"Volume mesh stats: {volume_mesh_stats.volume_mesh_name}")
volume_mesh_statistics : api.VolumeMeshStatistics = volume_mesh_stats.statistics
print(f" Vertices: {volume_mesh_statistics.num_vertices}")
print(f" Total volume: {volume_mesh_statistics.total_volume}")
visible_volume_mesh_stats = measure_operations.compute_all_visible_volume_mesh_statistics(requested_volume_mesh_stats)
print(f"Visible volume mesh stats count: {len(visible_volume_mesh_stats)}")
for result in visible_volume_mesh_stats:
visible_volume_mesh_stats_result : api.VolumeMeshStatisticsResult = result
visible_volume_mesh_statistics : api.VolumeMeshStatistics = visible_volume_mesh_stats_result.statistics
print(f" Volume mesh {visible_volume_mesh_stats_result.volume_mesh_name}: vertices={visible_volume_mesh_statistics.num_vertices}")
volume_mesh_stats_txt = r"C:\output\volume_mesh_statistics.txt"
measure_operations.export_volume_mesh_statistics_to_disk(volume_mesh_stats, volume_mesh_stats_txt)
volume_mesh_quality : api.VolumeMeshQualityResult = measure_operations.analyze_volume_mesh_quality(volume_mesh_name, api.VolumeMeshQualityMetric.TetAspectRatio)
print(f"Volume mesh quality: {volume_mesh_quality.volume_mesh_name}")
volume_mesh_quality_stats : api.QualityMetricStatistics = volume_mesh_quality.statistics
print(f" Mean: {volume_mesh_quality_stats.mean_value}")
volume_mesh_quality_txt = r"C:\output\volume_mesh_quality.txt"
measure_operations.export_volume_mesh_quality_to_disk(volume_mesh_quality, volume_mesh_quality_txt)
Primitive Fitting and Measurement Between Primitives​
if all_surfaces:
surface_name = all_surfaces[0]
surface_fit : api.PrimitiveFittingResult = measure_operations.fit_primitive_to_surface(surface_name, api.PrimitiveFittingType.Sphere)
print(f"Primitive fit (surface): {surface_fit.primitive_name}")
print(f" Center: {surface_fit.center}")
fitted_primitive_name = surface_fit.primitive_name
if all_masks:
mask_name = all_masks[0]
app.set_mask_3d_preview_quality(api.Mask3dPreviewQuality.Optimal)
app.generate_mask_3d_preview([mask_name])
mask_fit : api.PrimitiveFittingResult = measure_operations.fit_primitive_to_mask_3d_preview(mask_name, api.PrimitiveFittingType.Sphere)
print(f"Primitive fit (mask 3D preview): {mask_fit.primitive_name}")
measurement : api.PrimitiveMeasurementResult = measure_operations.measure_between_primitives(fitted_primitive_name, mask_fit.primitive_name, True)
print(f"Measurement distance: {measurement.distance}")
print(f"Measurement name: {measurement.measurement_name}")
print("Measure operations tutorial completed successfully.")
Related Resources​
- API Reference - API documentation
- Quick Reference - Common methods at a glance