Repository navigation
Releases: JolleyLab/slicerheart_4dflow
Release list
v0.3.1
Clinical test data set download.
New
-
clinical_test_data(revision)downloads a revision of the clinical test data set (15 de-identified 4D flow MRI cases in 3D Slicer native formats, CC BY 4.0, from the TestingData release) and returns the full path of the data set root:import slicerheart_4dflow as f4d root = f4d.clinical_test_data("rev001") case = f4d.load_case(root, f4d.dataset_cases(root)[0])
- The data sets are kept in
~/.SlicerHeart/slicerheart_4dflow_testingdata(oneclinical_<revision>/folder per revision), shared by every Python environment and 3D Slicer installation of the user;SLICERHEART_4DFLOW_TESTDATAorbase_dirselects another folder.cases=downloads only some cases. - The manifest of the revision (
clinical_manifest_<revision>.json, themanifest.jsonof the data set) lists the size and sha256 of every file and the zip that contains it; it is verified by the sha256 recorded in the package. Only missing or changed files are downloaded again; the cache is checked by the size and modification time of each file, without reading them. slicerheart_4dflow.testing_data.ClinicalTestingDatagives the cases of a revision from its manifest without downloading them, and downloads a case when it is needed (ensure_case).- Command line:
python -m slicerheart_4dflow.testing_data download [revision], andpackageto write the release files of a new revision.
- The data sets are kept in
Tests
- The clinical tests (marker
clinical) download the data set on first use instead of needing a local copy, and run in CI in a separate job that keeps the data set in the GitHub Actions cache.
Full list of changes: v0.3.0...v0.3.1
v0.3.0
Third release of the SlicerHeart 4D flow filters: noise-free images (synthetic phantoms) are handled, the velocity noise has one definition, and the hemodynamic quantities are computed 3 to 12 times faster.
Changed
- Automatic lumen segmentation grows closer to the vessel wall (
estimate_lumen). The lumen is grown into voxels whose RMS speed is abovegrowth_noise_factortimes that of the velocity noise. On 15 pediatric clinical cases, the velocity noise of the lumen estimate was 1.7 times (median, 1.1 to 2.6) that ofquality_report, because it was estimated in dark tissue too and with a biased estimator, so the lumen stopped short of the wall. On these cases the lumen volume grows by 21% (median, 5% to 30%). Lumens and plane flows computed with an earlier version differ; regenerate them. - One velocity noise definition for
quality_reportand the lumen estimate:noise_tissue_maskselects the tissue above the Otsu threshold of the magnitude (the noise scales with 1 / magnitude), andvelocity_noiseestimates the noise of each component (median of per-voxel variances, unbiased for Gaussian noise).velocity_noise_in_tissuereturns their RMS over the components, or each component withper_component=True. - The default
growth_noise_factoris 1.9 (was 2.0). It reproduces the flow error, coverage and leakage of the synthetic cases with known lumen.
Fixed
- Background correction failed on noise-free images ("only N static-tissue candidates"):
body_maskdropped voxels with constant velocity over time as zero filling or masked air, which on a noise-free phantom removed all static tissue. When many bright voxels have constant velocity, the body is now found by the Otsu threshold of the magnitude. Zero filling and masked air are dark, so measured data is not affected. - The lumen estimate failed on noise-free images ("no tissue selected by magnitude to estimate the velocity noise"). If no static tissue is left outside the lumen, the noise is estimated in all nonzero-magnitude voxels outside it (with a warning); a noise estimate of 0 gets a small speed floor, so rounding errors are not counted as flow.
Faster
On a clinical case (15 frames), with the same results:
| Step | v0.2.0 | v0.3.0 |
|---|---|---|
Lumen integrals (velocity_gradient on the lumen only) |
10.4 s | 3.6 s |
| Wall shear stress (one pseudo-inverse per sample pattern) | 4.8 s | 0.4 s |
| Pressure gradient | 35 s | 8 s |
| Relative pressure solve (frames in threads) | 25 s | 6.3 s |
Testing
- Noise-free phantoms with linear and quadratic background offsets (
tests/test_noise_free.py). - The clinical tests run case by case and keep one case in memory.
v0.2.0
Second release of the SlicerHeart 4D flow filters: clinical data support, new methods, fixes found on clinical data, and about 6 times faster preprocessing.
New
- Reading data prepared in 3D Slicer (
slicer_io,pip install slicerheart_4dflow[clinical]): volumes and volume sequences (.nrrd,.seq.nrrd), segmentations, plane markups, and whole test cases exported by SlicerHeart Import 4D Flow. Data sets use format 4:inputs/<case>(acquisition, annotations) separate fromoutputs/<case>, withmanifest.jsonat the data set root;dataset_cases(dataset)andload_case(dataset, case_id)read them. - Automatic lumen segmentation (
estimate_lumen): Otsu threshold of the PC-MRA on a 2x finer grid, resampled with VTK in physical space, grown to the vessel wall. - Noise mask by body mask (
body_mask, draft): a Kittler-Illingworth split of log magnitude against the temporal phase noise, which adapts to the air fraction of the field of view and is not fooled by coil shading; now the default ofnoise_maskand of the static tissue for background correction. - Multi-venc unwrapping (draft): dual- and triple-venc (
sdv,odv, the Schnell 2017 threshold rule), with a valve-jet phantom. - Background correction: the Pruitt 2019 WRLS + ARTO fitter (
arto). - Laplacian unwrapping: a periodic time axis for
laplacian4d(Loecher 2016), for retrospectively gated data. - Wall shear stress: the wall surface by VTK flying edges instead of scikit-image marching cubes.
- Validation tools: semi-synthetic references built from measured cases, a transfer audit that compares a case with a matched synthetic case, the encoding-direction self-check, and a clinical test suite with per-case baselines (a synthetic clinical case runs in CI).
Fixed
- Aliased voxels were marked as noise before unwrapping (and so excluded from it): with venc,
noise_maskandbody_maskuse wrap-invariant temporal differences. body_maskput the air into the body where the field of view has zero-filled voxels, and kept only the lumen in dark tissue without air.- The velocity noise of
quality_reportis estimated in tissue above the Otsu threshold again (it was 1.2 to 2.5 times too high with the body mask). - Plane flow: in-plane basis and disc-edge sampling; pathline emission times; WSS wall normals on anisotropic grids.
Faster
preprocess on a clinical case (160 x 120 x 80 voxels, 26 frames) takes 15 s instead of 88 s, with the same results: the Laplacian kernels, the spectral solves and the temporal statistics were rewritten to work frame by frame and in threads (#28, #41). leray and dfw divergence filtering are 6 to 8 times faster.
Changed
noise_maskand the background-correction candidates usebody_maskby default (magnitude_threshold="otsu"restores the Otsu threshold).- Test cases in format 3 (per-vendor folders, per-case manifest) are no longer read.
Known issues
- The EM of the war+msac wrap-around rejection does not converge within its iteration cap (#42).
body_maskand multi-venc are drafts, chosen on phantoms and a first clinical data set; their defaults may change.
Algorithms by Matthew Jolley (@mattjolley); clinical integration and validation by Andras Lasso (@lassoan).
Full list of changes: v0.1.0...v0.2.0
Testing data
Files used by the slicerheart_4dflow tests, downloaded on first use (see tests/conftest.py). This is not a version of the package and is not published to PyPI.
example_data_HR.h5
Aortic CFD velocity field (0.59 mm, with lumen mask), used as ground truth by the tests marked cfd.
- Source: 4DFlowNet by Edward Ferdian et al.:
data/example_data_HR.h5at commit7ec3b8269ac9d0f584bc7b6fe03138c1dabe2a8f(2020-05-28). - Reference: Ferdian E, Suinesiaputra A, Dubowitz DJ, et al. 4DFlowNet: Super-resolution 4D flow MRI using deep learning and computational fluid dynamics. Front Phys. 2020;8:138. https://doi.org/10.3389/fphy.2020.00138
- License: MIT, see the 4DFlowNet license.
Clinical test cases (clinical_* files)
De-identified clinical 4D flow MRI test cases (15 cases) in 3D Slicer native file formats, used by the tests marked clinical and available through slicerheart_4dflow.clinical_test_data("rev001"), which downloads and caches them. One zip per folder of the data set (clinical_inputs_<case>_acquisition_<revision>.zip, clinical_inputs_<case>_annotations_<revision>.zip, clinical_outputs_<case>_<revision>.zip, clinical_tests_<revision>.zip), clinical_README_<revision>.md (the description of the data set), and the manifest clinical_manifest_<revision>.json. The suffix is the revision of the files; later revisions are added next to it.
- Source: 4D flow MRI exams from a Siemens Avanto Fit (1.5 T, syngo MR E11), de-identified with the LUWAK anonymizer and exported to 3D Slicer formats by SlicerHeart Import 4D Flow. Measurement planes placed automatically; automatic lumen segmentations and outputs computed with slicerheart_4dflow 0.3.0 (
_rev001: data set revision rev04). - Reference: SlicerHeart 4D flow filters (JolleyLab).
- License: CC BY 4.0, with attribution to the SlicerHeart project. Please do not attempt to re-identify the subjects.
- Manifest:
clinical_manifest_<revision>.json(themanifest.jsonof the data set) has the metadata of the data set (format version, name, license, DOI), the revision, the path, size and sha256 of every other file of the data set and the zip that contains it, and the sha256 of every zip, so that only changed files need to be downloaded again.
v0.1.0
First release of the SlicerHeart 4D flow filters.
- Background phase (eddy current) correction:
ols,msac,wrls,war+msac - Velocity anti-aliasing (phase unwrapping): temporal, Laplacian 3D/4D, Laplacian then temporal
- Noise masking and PC-MRA
- Divergence-free filtering and denoising:
fdm,relaxed,leray,dfw - Plane flow quantification and mass-conservation QA
- Pathlines (numpy RK4 or VTK particle tracer) and centerline-based plane placement
Images with any voxel-to-world mapping (anisotropic, oblique, flipped, sheared) are supported through a 4x4 voxel_to_world matrix, in any world coordinate system (LPS or RAS). Requires Python 3.12 or later.
Algorithms by Matthew Jolley (@mattjolley).