Feature: Plane Metrics¶
Status¶
| Entry point | Status | Notes |
|---|---|---|
| GUI | Supported | Calculate && Save Metrics, Plane Curve, and automatic refresh after plane edits |
| CLI | Supported | part of the default batch order |
| Python API | Supported | through run_case() and run_batch() |
What It Does¶
Plane metrics compute time-resolved cross-sectional measurements for each plane and save them into plane_metrics.json. The same per-plane payload is also mirrored into planes.json and planes.h5, so one plane index has one consistent set of geometry and summaries across outputs. The GUI plane-metric step computes basic flow, area, and velocity without implicitly starting WSS, TKE, or pressure work. If derived arrays already exist, it reuses them. Batch runs compute only the derived fields explicitly requested through --with or requested_metrics.
For each unique segmentation phase, plane metrics build one thresholded VTK support mesh and reuse it across all planes. Each plane still has its own slice and connectivity selection, while repeated cardiac phases reuse the resulting slice specification. Plane centers remain local physical coordinates and are shifted by origin only for VTK slicing.
Generated planes are filtered before metric integration when their requested
branch has no cells in the segmentation-filtered cross-section. The exclusion
criterion is missing geometric support (area_mm2 == 0 after branch
selection), not a zero numerical flow value. This keeps real low-flow or
forward/reverse-cancelling planes. A path with no remaining valid planes stays
in the graph topology but has no path metric; its path IC is null/undefined,
and a fork that is missing a path metric is also reported as incomplete rather
than treating the missing path as zero flow.
When To Use It¶
- use it after planes exist
- use it when you need per-plane flow, area, and velocity curves
- use it when you need explicit
plane_indexvalues that line up withplanes.json,planes.h5, and the plane-rotation video labels - add
--with wss,tke,pgif you also want derived per-plane summaries;--with vortexcomputes whole-volume vortex fields and is not a plane summary - do not expect it to run without segmentation
Quick Use¶
GUI¶
- generate planes
- click
Calculate && Save Metrics - inspect the selected plane in the selection panel, ortho viewer, and
Plane Curvemode - when plane geometry needs correction, use
Edit Plane; releasing a handle recomputes only that plane and updates the metric and plane records - click
Calculate && Save Metricsafter interactive edits when a fully regeneratedplane_metrics_pixelwise.h5is required
CLI¶
Python API¶
Use the standard run_case() or run_batch() flow. Plane metrics run unless skip_plane_metrics=True.
Inputs¶
| Input | Required | Meaning |
|---|---|---|
| flow | yes | time-resolved velocity field |
| segmentation | yes | vessel mask for valid plane sampling |
| planes | yes | analysis planes |
Parameters¶
| Parameter | Type | Default | Where set | Effect | Code owner |
|---|---|---|---|---|---|
skip_plane_metrics |
bool | False |
batch config or CLI/API | disable the whole plane-metric export step | autoflow/processing.py |
use_multithread |
bool | True |
configs/batch.json |
allow adaptive plane parallelism; sets below 128 planes stay serial because shared VTK geometry is faster without scheduling overhead | autoflow/core/pipeline.py |
Outputs¶
| Output file or object | Created when | Meaning |
|---|---|---|
plane_metrics.json |
plane metrics run | one metric record per plane with explicit plane_index and time-resolved fields |
plane_qc.json |
plane metrics run | QC for paths and forks |
plane_metrics_pixelwise.h5 |
plane metrics run | per-plane slice-cellwise derived samples |
planes.json |
planes exist | geometry, placement_mode, label_name, and attached plane summaries |
planes.h5 |
planes exist | one root group per plane such as plane_0000, with placement_mode, label_name, the same per-plane payload, and a payload_json mirror |
pwv.json |
PWV runs successfully | saved PWV results for configured label groups |
pwv_<group>.png |
PWV plotting succeeds | saved PWV plots |
Main metric fields¶
| Field | Type or unit | Meaning | Where to see it |
|---|---|---|---|
plane_index |
int | stable plane number for this record; matches planes.json, planes.h5, and plane-video labels |
plane_metrics.json, planes.json, planes.h5 |
center, normal |
3-element arrays | plane center and plane normal in workspace coordinates | plane_metrics.json, planes.json, planes.h5 |
path_index |
int | centerline path that generated this plane | plane_metrics.json, planes.json, planes.h5, GUI selection panel |
distance |
mm | cumulative distance from the path start to the plane location | plane_metrics.json, planes.json, planes.h5 |
peakv_cm_s |
cm/s | peak absolute through-plane velocity over the whole cardiac cycle | plane_metrics.json, GUI selection panel, ortho viewer |
flowrate_mL_s |
array, mL/s | raw per-timepoint flow-rate curve through the plane | plane_metrics.json, Plane Curve mode, planes.h5 |
netflow_mL_beat |
mL/beat | beat-integrated absolute flow derived from the mean of flowrate_mL_s and RR |
plane_metrics.json, GUI selection panel, planes.h5 |
area_mm2 |
array, mm^2 | segmented cross-sectional area per timepoint | plane_metrics.json, Plane Curve mode, planes.h5 |
meanv_cm_s, meanv_cm_s_t |
cm/s | mean through-plane velocity summary and its per-timepoint curve | plane_metrics.json, ortho viewer, Plane Curve mode, planes.h5 |
flowrate_forward_mL_s, flowrate_reverse_mL_s |
arrays, mL/s | forward and reverse components after AutoFlow resolves the forward direction along the local path | plane_metrics.json, Plane Curve mode, planes.h5 |
meanv_signed_cm_s, meanv_signed_cm_s_t |
cm/s | signed mean velocity aligned to the resolved forward direction | plane_metrics.json, planes.h5 |
path_ic, fork_ic |
unitless or null |
internal-consistency checks along a path and across forks; paths with fewer than two valid planes and forks missing a path metric are reported as null/undefined rather than a misleading perfect score or zero |
plane_metrics.json, plane_qc.json, GUI Internal Consistency mode |
forward_sign, forward_sign_source |
int and string | how the forward direction was resolved for the plane | plane_metrics.json, planes.h5 |
local_path_tangent, local_path_direction, normal_tangent_cos |
vector, text, scalar | relationship between the plane normal and the local centerline tangent | plane_metrics.json, planes.h5 |
tke_* |
J/m^3 | derived TKE summaries; present only when TKE is available and requested | plane_metrics.json, planes.h5, Plane Curve mode |
pressure_gradient_* |
Pa/m | derived pressure-gradient summaries; present only when pressure analysis is requested | plane_metrics.json, planes.h5, Plane Curve mode |
relative_pressure_* |
Pa | derived relative-pressure summaries; present only when pressure analysis is requested | plane_metrics.json, planes.h5, Plane Curve mode |
wss_wall_* |
Pa | derived wall-shear summaries; present only when WSS is requested | plane_metrics.json, planes.h5, Plane Curve mode |
label_name |
string | readable plane label resolved from configs/labels.json -> label_map |
planes.json, planes.h5 |
path_info |
object | saved path metadata such as direction text, endpoints, and fork linkage | planes.json, planes.h5 |
Naming rules¶
- fields ending in
_tare time-resolved arrays in cardiac-phase order - fields ending in
_mean,_peak, or_p95are scalar summaries over the sampled plane data forwardandreverseuse the resolved local forward direction;signedkeeps that sign convention in one curve
Limitations¶
- segmentation is required
- plane metrics depend on valid plane placement
- derived summaries attached to planes depend on opting in to the corresponding derived metrics
- requesting one derived metric does not implicitly compute the others; for example,
--with pgattaches pressure summaries without running WSS WSS / TKE / Pressure / Vortexaugments existing GUI plane metrics with WSS, TKE, and pressure summaries after computing missing derived families; vortex fields are whole-volume only and do not add plane summaries- interactive plane edits defer the complete pixelwise H5 resampling pass until the explicit metric-save step
- support-mesh reuse assumes identical mask bytes represent identical geometry; changing segmentation content creates a new support mesh
Where To Change Code¶
| Change you want | Edit here | Also check | Tests |
|---|---|---|---|
| plane metric computation | autoflow/algorithms/metrics.py |
autoflow/core/pipeline.py |
tests/test_smoke_phantoms.py, tests/test_pressure_gradient_phantom.py |
| plane metric save format | autoflow/core/pipeline.py, autoflow/plane_io.py |
autoflow/reporting.py |
tests/test_pressure_gradient_phantom.py |
| GUI plane metric refresh and PWV dock | autoflow/ui/app.py, autoflow/ui/ortho_viewer.py |
autoflow/core/pipeline.py, autoflow/algorithms/pwv.py |
GUI manual verification |
Tests¶
~/miniconda3/envs/ryy/bin/python -m pytest tests/test_smoke_phantoms.py -q~/miniconda3/envs/ryy/bin/python -m pytest tests/test_pressure_gradient_phantom.py -q
Common Problems¶
| Symptom | Likely cause | Fix |
|---|---|---|
| metrics step is skipped | no segmentation or no flow | load or create segmentation and verify input data |
| saved metrics do not match moved planes | plane edits were not finalized | finish drag interaction and let the GUI recompute metrics |
| it is hard to match a metric row to a rendered plane | plane labels were not inspected together with saved outputs | use plane_index in plane_metrics.json, planes.json, planes.h5, and the the plane-video index labels in planes_rotate.mp4, which default to planeidx=<index> and can be restyled in configs/video_exporting.json -> plane_video.label |