diff --git a/.github/workflows/nightly-health.yml b/.github/workflows/nightly-health.yml index 31e9bb8..6b0a604 100644 --- a/.github/workflows/nightly-health.yml +++ b/.github/workflows/nightly-health.yml @@ -58,7 +58,7 @@ jobs: # Python 3.11 is required because the [physicsnemo] extra pulls in # nvidia-physicsnemo, which requires Python >= 3.11. run: | - & py -m venv "$env:RUNNER_TEMP\physiotwin4d-venv" + & py -3.11 -m venv "$env:RUNNER_TEMP\physiotwin4d-venv" echo "$env:RUNNER_TEMP\physiotwin4d-venv\Scripts" >> $env:GITHUB_PATH - name: Cache uv packages diff --git a/.gitignore b/.gitignore index 1e9db68..3e12bf9 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,9 @@ build __pycache__ _version.py htmlcov +.cursor +.vscode/* +!.vscode/settings.json # AI files .claude diff --git a/data/DirLab-4DCT/README.md b/data/DirLab-4DCT/README.md index be5199d..686b65d 100644 --- a/data/DirLab-4DCT/README.md +++ b/data/DirLab-4DCT/README.md @@ -68,7 +68,7 @@ points for registration validation. ### Dataset Details -- **Format**: `.mhd`/`.raw` (MetaImage format) +- **Format**: `.mhd` headers + `.img` raw volumes (MetaImage format) - **Cases**: 10 patient cases (Case 1-10) - **Phases**: 10 respiratory phases per case (T00-T90) - **Content**: Non-contrast lung CT diff --git a/data/README.md b/data/README.md index dcfa81e..bc0b525 100644 --- a/data/README.md +++ b/data/README.md @@ -1,61 +1,33 @@ # PhysioTwin4D Data Directory -This directory holds the example datasets used by PhysioTwin4D's tutorials, -experiments, and tests. Each subdirectory is one dataset and has its own -`README.md` with the download URL(s), directory layout, data sizes, and the -exact `physiotwin4d-download-data` command for that dataset. This file is -just the map — see the subdirectory README before downloading anything. +This directory holds the sample datasets used for experiments, testing, and +development of the PhysioTwin4D library. Each subdirectory contains one +dataset and its own `README.md` with download instructions, specifications, +and citation — this file is just an index; treat the per-dataset READMEs as +the source of truth. ## Datasets -| Directory | Data Type | Provided By | Auto-Download | -| ----------------------------------- | ------------------------------------------------------- | --------------------------------------- | ------------- | -| [`Slicer-Heart-CT/`](Slicer-Heart-CT/README.md) | 4D gated cardiac CT (`.seq.nrrd`) | Jolley Lab (CHOP) / SlicerHeart on GitHub | Yes | -| [`DirLab-4DCT/`](DirLab-4DCT/README.md) | 4D lung CT respiratory benchmark + landmarks (`.mhd/.raw`) | DIR-Lab (Emory / MD Anderson) | No — manual, may require registration | -| [`KCL-Heart-Model/`](KCL-Heart-Model/README.md) | Statistical heart shape model meshes (`.vtk`) | King's College London, via Zenodo | Yes | -| [`CHOP-Valve4D/`](CHOP-Valve4D/README.md) | FEBio valve FE model, converted to VTK/ITK + Simpleware segmentation | Jolley Lab (CHOP), converted by PhysioTwin4D | Yes | - -[`data/test/`](test/README.md) is not a dataset — it is a cache -automatically managed by the pytest infrastructure (mainly from -`Slicer-Heart-CT`) and is not used by the workflows, tutorials, or CLIs. - -## Downloading Data - -Datasets marked **Yes** above can be fetched with the -`physiotwin4d-download-data` CLI (or the corresponding -`DataDownloadTools.Download*` method), for example: - -```bash -physiotwin4d-download-data Slicer-Heart-CT --directory data/Slicer-Heart-CT -physiotwin4d-download-data KCL-Heart-Model --directory data/KCL-Heart-Model -physiotwin4d-download-data CHOP-Valve4D --directory data/CHOP-Valve4D -``` - -Datasets marked **No** must be downloaded by hand following the -instructions in that dataset's own README (`DirLab-4DCT/README.md`). - -### Verification Helpers - -Each dataset also has a `DataDownloadTools.Verify*Data()` helper that checks -whether the expected files are already present, so scripts can skip -downloading when the data is cached: - -```python -from physiotwin4d import DataDownloadTools - -DataDownloadTools.VerifySlicerHeartCTData("data/Slicer-Heart-CT") -DataDownloadTools.VerifyDirLab4DCTData("data/DirLab-4DCT") -DataDownloadTools.VerifyKCLHeartModelData("data/KCL-Heart-Model") -DataDownloadTools.VerifyCHOPValve4DData("data/CHOP-Valve4D") -``` - -## Guidelines - -- Keep original downloaded data unmodified; write experiment/tutorial - results under `experiments/*/results/` or `tutorials/*/results/`, not - back into `data/`. -- Always respect the license and citation requirements of each dataset — - see the "Citation" / "Acknowledgement" section in the relevant - subdirectory README. -- If you add a new dataset, add both a row above and a subdirectory - `README.md` following the existing datasets as a template. +| Directory | Description | Provided By | Download | README | +| --- | --- | --- | --- | --- | +| `Slicer-Heart-CT/` | 4D cardiac CT with gated cardiac phases | Jolley Lab, Children's Hospital of Philadelphia (CHOP) | Automatic | [Slicer-Heart-CT/README.md](Slicer-Heart-CT/README.md) | +| `DirLab-4DCT/` | 4D lung CT respiratory motion benchmark | DIR-Lab, MD Anderson Cancer Center / Emory University | Manual | [DirLab-4DCT/README.md](DirLab-4DCT/README.md) | +| `KCL-Heart-Model/` | Statistical shape model of the heart | King's College London (KCL) | Automatic | [KCL-Heart-Model/README.md](KCL-Heart-Model/README.md) | +| `CHOP-Valve4D/` | 4D valve reconstruction models | Jolley Lab, CHOP (original FEBio model) | Automatic | [CHOP-Valve4D/README.md](CHOP-Valve4D/README.md) | +| `test/` | pytest-managed cache; not a downloadable dataset | — | N/A | [test/README.md](test/README.md) | + +## Automatic Download + +`Slicer-Heart-CT`, `KCL-Heart-Model`, and `CHOP-Valve4D` can be fetched with +the `physiotwin4d-download-data` CLI or `DataDownloadTools`; see each +dataset's README for the exact command. `DirLab-4DCT` has no automatic +downloader — DIR-Lab distributes each case individually and may require +registration, so it must be obtained manually; see +[DirLab-4DCT/README.md](DirLab-4DCT/README.md). + +## Notes + +- Always cite the original data source in publications — see each dataset's + README for the required citation. +- The full set of datasets is ~10-20 GB; ensure adequate disk space before + downloading everything. diff --git a/src/physiotwin4d/vtk_to_usd/usd_utils.py b/src/physiotwin4d/vtk_to_usd/usd_utils.py index 7408bc1..7d06626 100644 --- a/src/physiotwin4d/vtk_to_usd/usd_utils.py +++ b/src/physiotwin4d/vtk_to_usd/usd_utils.py @@ -163,16 +163,11 @@ def numpy_to_vt_array(array: NDArray, data_type: DataType) -> Any: array_uc = array.astype(np.uint8) return Vt.UCharArray.FromNumpy(array_uc.flatten()) - elif data_type in [DataType.SHORT, DataType.USHORT]: + else: # DataType.SHORT, DataType.USHORT # Convert to int array_i = array.astype(np.int32) return Vt.IntArray.FromNumpy(array_i.flatten()) - else: - # Fallback to float - array_f = array.astype(np.float32) - return Vt.FloatArray.FromNumpy(array_f.flatten()) - def get_sdf_value_type(data_type: DataType, num_components: int) -> Sdf.ValueTypeName: """Get appropriate SDF value type for primvar creation. @@ -214,12 +209,9 @@ def get_sdf_value_type(data_type: DataType, num_components: int) -> Sdf.ValueTyp elif data_type in [DataType.UCHAR, DataType.CHAR]: return Sdf.ValueTypeNames.UCharArray - elif data_type in [DataType.SHORT, DataType.USHORT]: + else: # DataType.SHORT, DataType.USHORT return Sdf.ValueTypeNames.IntArray - else: - return Sdf.ValueTypeNames.FloatArray - def sanitize_primvar_name(name: str) -> str: """Sanitize a name to be USD-compliant. diff --git a/tests/README.md b/tests/README.md index ad4adaa..0798ced 100644 --- a/tests/README.md +++ b/tests/README.md @@ -254,7 +254,7 @@ When creating new tests: ## Test Data ### Slicer-Heart-CT Dataset -- **Source**: [Slicer-Heart-CT GitHub](https://github.com/Slicer-Heart-CT/Slicer-Heart-CT) +- **Source**: [SlicerHeart GitHub](https://github.com/SlicerHeart/SlicerHeart) - **File**: `TruncalValve_4DCT.seq.nrrd` (~1.2 GB) - **Content**: 21-phase pediatric cardiac CT - **Usage**: Tests use first 2 time points for speed diff --git a/tutorials/tutorial_01_heart_gated_ct_to_usd.py b/tutorials/tutorial_01_heart_gated_ct_to_usd.py index eba2bd3..71bd7a9 100644 --- a/tutorials/tutorial_01_heart_gated_ct_to_usd.py +++ b/tutorials/tutorial_01_heart_gated_ct_to_usd.py @@ -60,7 +60,7 @@ Data Required ------------- See data/README.md for download instructions and dataset licensing. -Dataset: Slicer-Heart-CT - https://github.com/Slicer-Heart-CT/Slicer-Heart-CT +Dataset: Slicer-Heart-CT - https://github.com/SlicerHeart/SlicerHeart This script expects the data to already exist at ``data/Slicer-Heart-CT/TruncalValve_4DCT.seq.nrrd``. Run the repository data download notebook or download the file manually before running this tutorial.