|
| 1 | +# TPTBox Core |
| 2 | + |
| 3 | +The `core` subpackage is the foundation of TPTBox. It provides the three primary abstractions — |
| 4 | +`NII`, `POI`, and `BIDS_FILE` — along with helper utilities for array operations and anatomical constants. |
| 5 | + |
| 6 | +## Key Classes and Functions |
| 7 | + |
| 8 | +### `nii_wrapper.py` — NIfTI image wrapper |
| 9 | + |
| 10 | +| Symbol | Description | |
| 11 | +|---|---| |
| 12 | +| `NII` | Wraps `nibabel.Nifti1Image`; the central image type throughout TPTBox | |
| 13 | +| `NII.load(path, seg)` | Load a NIfTI file from disk (classmethod) | |
| 14 | +| `NII.from_numpy(arr, affine, seg)` | Construct from a numpy array and affine matrix | |
| 15 | +| `NII.reorient(axcodes_to)` | Reorient to a canonical axis code (e.g. `("R","A","S")`) | |
| 16 | +| `NII.rescale(voxel_spacing)` | Resample to new voxel spacing in mm | |
| 17 | +| `NII.resample_from_to(other)` | Resample to match the grid of another `NII` | |
| 18 | +| `NII.apply_mask(mask)` | Zero-out voxels outside a binary/label mask | |
| 19 | +| `NII.map_labels(label_map)` | Remap integer labels | |
| 20 | +| `NII.save(path)` | Save to disk as `.nii` or `.nii.gz` | |
| 21 | +| `NII.get_array()` | Return a copy of the underlying numpy array | |
| 22 | +| `NII.get_seg_array()` | Same as `get_array()` but asserts `seg=True` | |
| 23 | +| `Image_Reference` | Type alias: `BIDS_FILE | Nifti1Image | Path | str | NII` | |
| 24 | + |
| 25 | +### `bids_files.py` — BIDS dataset navigation |
| 26 | + |
| 27 | +| Symbol | Description | |
| 28 | +|---|---| |
| 29 | +| `BIDS_Global_info` | Scans a dataset root and indexes all BIDS files | |
| 30 | +| `BIDS_Global_info.enumerate_subjects()` | Iterate over subjects as `(subject_id, Subject_Container)` | |
| 31 | +| `Subject_Container` | Per-subject file index; entry point for queries | |
| 32 | +| `Subject_Container.new_query()` | Returns a `Searchquery` for this subject | |
| 33 | +| `BIDS_FILE` | One file parsed into BIDS entities (sub, ses, format, …) | |
| 34 | +| `BIDS_FILE.open_nii()` | Load this file's NIfTI | |
| 35 | +| `BIDS_FILE.get_changed_path(...)` | Derive a new path with changed BIDS entities | |
| 36 | +| `Searchquery` | Fluent query builder: `.filter()`, `.loop_dict()`, `.first()` | |
| 37 | +| `BIDS_Family` | `dict[str, list[BIDS_FILE]]` grouping files by format | |
| 38 | + |
| 39 | +### `poi.py` — Points of Interest |
| 40 | + |
| 41 | +| Symbol | Description | |
| 42 | +|---|---| |
| 43 | +| `POI` | Maps `(vertebra_id, subregion_id) → (x, y, z)` | |
| 44 | +| `calc_centroids(seg_nii)` | Compute centroids for every label in a segmentation | |
| 45 | +| `calc_poi_from_subreg_vert(vert, subreg)` | Compute POIs from paired vertebra + subregion segmentations | |
| 46 | +| `POI.save(path)` | Serialise to JSON | |
| 47 | +| `POI.load(path)` | Deserialise from JSON | |
| 48 | +| `POI.to_global(ref)` | Convert from voxel to world (mm) coordinates | |
| 49 | +| `POI.to_local(ref)` | Convert from world to voxel coordinates | |
| 50 | + |
| 51 | +### `np_utils.py` — NumPy utilities |
| 52 | + |
| 53 | +| Symbol | Description | |
| 54 | +|---|---| |
| 55 | +| `np_extract_label(arr, label)` | Extract a single label as a binary mask | |
| 56 | +| `np_center_of_mass(arr)` | Per-label centre-of-mass | |
| 57 | +| `np_volume(arr)` | Per-label voxel count | |
| 58 | +| `np_bbox_binary(mask)` | Bounding-box slice tuple for a binary array | |
| 59 | +| `np_dilate_msk(arr, mm, zoom)` | Morphological dilation by `mm` millimetres | |
| 60 | +| `np_erode_msk(arr, mm, zoom)` | Morphological erosion | |
| 61 | +| `np_fill_holes(arr)` | Fill holes per label | |
| 62 | +| `np_connected_components(arr)` | Label connected components | |
| 63 | +| `np_map_labels(arr, label_map)` | Remap label integers via a dict | |
| 64 | +| `np_unique(arr)` | Unique values (faster than `np.unique` for uint arrays) | |
| 65 | + |
| 66 | +### `vert_constants.py` — Anatomical constants |
| 67 | + |
| 68 | +| Symbol | Description | |
| 69 | +|---|---| |
| 70 | +| `Location` | `IntEnum` of anatomical subregion IDs (used as POI keys) | |
| 71 | +| `Vertebra_Instance` | Maps integer IDs → anatomical names (C1–S1) | |
| 72 | +| `v_name2idx` | Dict: `"L1" → 20`, etc. | |
| 73 | +| `v_idx2name` | Dict: `20 → "L1"`, etc. | |
| 74 | +| `v_idx_order` | Canonical sort order for vertebra IDs | |
| 75 | +| `ZOOMS` | Type alias: `tuple[float, float, float]` | |
| 76 | +| `AX_CODES` | Type alias: `tuple[str, str, str]` | |
| 77 | +| `AFFINE` | Type alias: `np.ndarray` (4×4) | |
| 78 | + |
| 79 | +## Quick Example |
| 80 | + |
| 81 | +```python |
| 82 | +from TPTBox import NII, BIDS_Global_info, calc_centroids |
| 83 | + |
| 84 | +# Load and resample a CT |
| 85 | +ct = NII.load("sub-001_ct.nii.gz", seg=False) |
| 86 | +ct_ras = ct.reorient(("R", "A", "S")).rescale((1.0, 1.0, 1.0)) |
| 87 | + |
| 88 | +# Compute centroids from a segmentation |
| 89 | +seg = NII.load("sub-001_seg.nii.gz", seg=True) |
| 90 | +poi = calc_centroids(seg) |
| 91 | +print(poi) |
| 92 | + |
| 93 | +# Scan a BIDS dataset |
| 94 | +bids = BIDS_Global_info(["dataset/"], parents=["rawdata"]) |
| 95 | +for subj, container in bids.enumerate_subjects(): |
| 96 | + t2 = container.new_query().filter("format", "T2w").first() |
| 97 | +``` |
0 commit comments