model¶
xvr.model.augmentations
¶
xvr.model.inference
¶
predict_pose
¶
predict_pose(
model: PoseRegressor,
config: dict,
img: Float[Tensor, "1 1 H W"],
sdd: float,
delx: float,
dely: float,
x0: float,
y0: float,
) -> RigidTransform
Regress the camera pose of an X-ray with a trained pose regressor.
The X-ray is resampled to the intrinsics the model was trained on, center cropped, and normalized before being passed through the network. This is how a checkpoint is used as an initializer for iterative registration.
| PARAMETER | DESCRIPTION |
|---|---|
model
|
Trained
TYPE:
|
config
|
The checkpoint's saved training config, supplying the model's
assumed
TYPE:
|
img
|
X-ray image tensor of shape
TYPE:
|
sdd
|
Source-to-detector distance of the X-ray, in millimeters.
TYPE:
|
delx
|
Pixel spacing of the X-ray along the x-axis, in millimeters.
TYPE:
|
dely
|
Pixel spacing of the X-ray along the y-axis, in millimeters.
Must equal
TYPE:
|
x0
|
Detector origin offset along the x-axis, in millimeters.
TYPE:
|
y0
|
Detector origin offset along the y-axis, in millimeters.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
RigidTransform
|
The predicted camera pose. |
Source code in src/xvr/model/inference.py
xvr.model.loss
¶
DiceMetric
¶
forward
¶
Compute 2D Dice coefficient between to multi-channel labelmaps. Assumes the first channel in each image is background.
Equivalent to monai.metrics.DiceMetric(include_background=False, reduction="none")
Source code in src/xvr/model/loss.py
HausdorffLoss
¶
Differentiable Hausdorff loss via the distance-transform formulation of Karimi & Salcudean (2019). The distance transform is approximated by iterated morphological erosion (max-pool on the inverted mask) and treated as a fixed spatial weight; gradients flow through (y_pred - y_true)^2.
L = mean( (y_pred - y_true)^2 * (DT(y_true)^a + DT(y_pred)^a) )
Source code in src/xvr/model/loss.py
xvr.model.network
¶
PoseRegressor
¶
PoseRegressor(
model_name,
parameterization,
convention=None,
pretrained=False,
height=256,
unit_conversion_factor=1000.0,
**kwargs,
)
A PoseRegressor is comprised of a pretrained backbone model that extracts features from an input X-ray and two linear layers that decode these features into rotational and translational camera pose parameters, respectively.
Source code in src/xvr/model/network.py
load_model
¶
Load a pretrained pose regression model
Source code in src/xvr/model/network.py
xvr.model.sampler
¶
get_random_pose
¶
get_random_pose(
alphamin,
alphamax,
betamin,
betamax,
gammamin,
gammamax,
txmin,
txmax,
tymin,
tymax,
tzmin,
tzmax,
batch_size,
)
Generate a batch of random poses in SE(3) using specified ranges.
Source code in src/xvr/model/sampler.py
xvr.model.scheduler
¶
WarmupCosineSchedule
¶
Linear warmup and then cosine decay.
Linearly increases learning rate from 0 to 1 over warmup_steps training steps.
Decreases learning rate from 1. to 0. over remaining t_total - warmup_steps steps following a cosine curve.
If cycles (default=0.5) is different from default, learning rate follows cosine function after warmup.
Source code in src/xvr/model/scheduler.py
xvr.model.trainer
¶
Trainer
¶
Trainer(
volpath: str,
maskpath: str | None,
outpath: str,
alphamin: float,
alphamax: float,
betamin: float,
betamax: float,
gammamin: float,
gammamax: float,
txmin: float,
txmax: float,
tymin: float,
tymax: float,
tzmin: float,
tzmax: float,
sdd: float,
height: int,
delx: float,
orientation: str = "AP",
reverse_x_axis: bool = False,
parameterization: str = "quaternion_adjugate",
convention: str = "ZXY",
model_name: str = "resnet18",
pretrained: bool = True,
norm_layer: str = "groupnorm",
unit_conversion_factor: float = 1000.0,
p_augmentation: float = 0.5,
lr: float = 0.005,
weight_ncc: float = 1.0,
weight_geo: float = 0.01,
weight_dice: float = 1.0,
weight_haus: float = 0.1,
batch_size: int = 116,
n_total_itrs: int = 1000000,
n_warmup_itrs: int = 1000,
n_grad_accum_itrs: int = 4,
n_save_every_itrs: int = 1000,
disable_scheduler: bool = False,
ckptpath: str | None = None,
reuse_optimizer: bool = False,
warp: str | None = None,
invert: bool = False,
patch_size: tuple[int, int, int] | None = None,
num_workers: int = 4,
pin_memory: bool = False,
weights: list[float] | None = None,
img_threshold: float = 0.1,
mask_threshold: float = 0.05,
n_samples: int = 500,
geodesic_only: bool = False,
)
Train a pose regression model.
| PARAMETER | DESCRIPTION |
|---|---|
volpath
|
CT or directory of CTs for pretraining.
TYPE:
|
maskpath
|
Optional labelmaps corresponding to the CTs.
TYPE:
|
outpath
|
Directory in which to save model weights.
TYPE:
|
alphamin
|
Minimum primary angle (in degrees).
TYPE:
|
alphamax
|
Maximum primary angle (in degrees).
TYPE:
|
betamin
|
Minimum secondary angle (in degrees).
TYPE:
|
betamax
|
Maximum secondary angle (in degrees).
TYPE:
|
gammamin
|
Minimum tertiary angle (in degrees).
TYPE:
|
gammamax
|
Maximum tertiary angle (in degrees).
TYPE:
|
txmin
|
Minimum x-offset (in millimeters).
TYPE:
|
txmax
|
Maximum x-offset (in millimeters).
TYPE:
|
tymin
|
Minimum y-offset (in millimeters).
TYPE:
|
tymax
|
Maximum y-offset (in millimeters).
TYPE:
|
tzmin
|
Minimum z-offset (in millimeters).
TYPE:
|
tzmax
|
Maximum z-offset (in millimeters).
TYPE:
|
sdd
|
Source-to-detector distance (in millimeters).
TYPE:
|
height
|
DRR height (in pixels).
TYPE:
|
delx
|
DRR pixel size (in millimeters / pixel).
TYPE:
|
orientation
|
Orientation of CT volumes.
TYPE:
|
reverse_x_axis
|
Horizontally flip the rendered DRRs.
TYPE:
|
parameterization
|
Parameterization of SO(3) for regression.
TYPE:
|
convention
|
If parameterization='euler_angles', specify order.
TYPE:
|
model_name
|
Name of model to instantiate from the timm library.
TYPE:
|
pretrained
|
Load pretrained ImageNet-1k weights.
TYPE:
|
norm_layer
|
Normalization layer.
TYPE:
|
unit_conversion_factor
|
Scale factor for translation prediction (e.g., from m to mm).
TYPE:
|
p_augmentation
|
Base probability of image augmentations during training.
TYPE:
|
lr
|
Maximum learning rate.
TYPE:
|
weight_ncc
|
Weight on mNCC loss term.
TYPE:
|
weight_geo
|
Weight on geodesic loss term.
TYPE:
|
weight_dice
|
Weight on Dice loss term.
TYPE:
|
weight_haus
|
Weight on Haussdorff loss term.
TYPE:
|
batch_size
|
Number of DRRs per batch.
TYPE:
|
n_total_itrs
|
Number of iterations for training the model.
TYPE:
|
n_warmup_itrs
|
Number of iterations for warming up the learning rate.
TYPE:
|
n_grad_accum_itrs
|
Number of iterations for gradient accumulation.
TYPE:
|
n_save_every_itrs
|
Number of iterations before saving a new model checkpoint.
TYPE:
|
disable_scheduler
|
Turn off cosine learning rate scheduler.
TYPE:
|
ckptpath
|
Checkpoint of a pretrained pose regressor.
TYPE:
|
reuse_optimizer
|
Initialize the previous optimizer's state.
TYPE:
|
warp
|
SimpleITK transform to warp input CT to checkpoint's reference frame.
TYPE:
|
invert
|
Whether to invert the warp or not.
TYPE:
|
patch_size
|
Optional random crop size; if None, return entire volume. |
num_workers
|
Number of subprocesses to use in the dataloader.
TYPE:
|
pin_memory
|
Copy volumes into CUDA pinned memory before returning.
TYPE:
|
weights
|
Probability for sampling each volume in volpath. |
img_threshold
|
Minimum fraction of foreground pixels to keep a DRR.
TYPE:
|
mask_threshold
|
Minimum fraction of mask pixels to keep a DRR.
TYPE:
|
Source code in src/xvr/model/trainer.py
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 | |
xvr.model.utils
¶
initialize_subjects
¶
initialize_subjects(
volpath: str,
maskpath: str | None,
orientation: str | None,
patch_size: tuple | None,
num_samples: int,
num_workers: int,
pin_memory: bool,
weights: tuple[float, ...] | None = None,
replacement: bool = True,
) -> tuple[Subject | SubjectsLoader, bool]
Load the CT (or CTs) to render training DRRs from.
A single volume is read eagerly. A directory is loaded lazily into a weighted-sampling dataloader, optionally serving random patches rather than whole volumes. Volumes and masks are matched by filename across the two directories.
| RETURNS | DESCRIPTION |
|---|---|
subjects
|
A single
TYPE:
|
single_subject
|
True if
TYPE:
|
Source code in src/xvr/model/utils.py
initialize_modules
¶
initialize_modules(
model_name,
pretrained,
parameterization,
convention,
norm_layer,
unit_conversion_factor,
sdd,
height,
delx,
orientation,
reverse_x_axis,
lr,
n_total_itrs,
n_warmup_itrs,
n_grad_accum_itrs,
subject,
disable_scheduler,
ckptpath,
reuse_optimizer,
) -> tuple[
PoseRegressor,
DRR,
Compose,
Optimizer,
IdentitySchedule | WarmupCosineSchedule,
int,
int,
]
Construct the model, renderer, and optimizer for a training run.
Restores model weights from ckptpath when given, and the optimizer and
scheduler state as well when reuse_optimizer is set. With more than one
subject the DRR module is built against a dummy CT, since each step swaps in
its own volume.
| RETURNS | DESCRIPTION |
|---|---|
model
|
The pose regressor.
TYPE:
|
drr
|
The differentiable renderer.
TYPE:
|
transforms
|
X-ray preprocessing shared with inference.
TYPE:
|
optimizer
|
The optimizer.
TYPE:
|
scheduler
|
The learning rate scheduler.
TYPE:
|
start_itr
|
Iteration to resume from, 0 unless reusing an optimizer.
TYPE:
|
model_number
|
Checkpoint number to resume from.
TYPE:
|
Source code in src/xvr/model/utils.py
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 | |
initialize_coordinate_frame
¶
initialize_coordinate_frame(
warp: str | Path | None, img: str | Path, invert: bool
) -> RigidTransform | None
Read the rigid transform reframing a CT into a checkpoint's frame.
| PARAMETER | DESCRIPTION |
|---|---|
warp
|
Path to a SimpleITK transform, or None for no reframing. |
img
|
Path to the CT the transform is defined against. |
invert
|
If True, invert the transform.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
RigidTransform | None
|
The transform, or None if |