|
21 | 21 | from .optpkg import optional_package
|
22 | 22 | spnd, _, _ = optional_package('scipy.ndimage')
|
23 | 23 |
|
24 |
| -from .affines import AffineError, to_matvec, from_matvec, append_diag |
| 24 | +from .affines import AffineError, to_matvec, from_matvec, append_diag, rescale_affine |
25 | 25 | from .spaces import vox2out_vox
|
26 | 26 | from .nifti1 import Nifti1Image
|
| 27 | +from .orientations import axcodes2ornt, io_orientation, ornt_transform |
27 | 28 | from .imageclasses import spatial_axes_first
|
28 | 29 |
|
29 | 30 | SIGMA2FWHM = np.sqrt(8 * np.log(2))
|
@@ -310,3 +311,80 @@ def smooth_image(img,
|
310 | 311 | mode=mode,
|
311 | 312 | cval=cval)
|
312 | 313 | return out_class(sm_data, img.affine, img.header)
|
| 314 | + |
| 315 | + |
| 316 | +def conform(from_img, |
| 317 | + out_shape=(256, 256, 256), |
| 318 | + voxel_size=(1.0, 1.0, 1.0), |
| 319 | + order=3, |
| 320 | + cval=0.0, |
| 321 | + orientation='RAS', |
| 322 | + out_class=None): |
| 323 | + """ Resample image to ``out_shape`` with voxels of size ``voxel_size``. |
| 324 | +
|
| 325 | + Using the default arguments, this function is meant to replicate most parts |
| 326 | + of FreeSurfer's ``mri_convert --conform`` command. Specifically, this |
| 327 | + function: |
| 328 | + - Resamples data to ``output_shape`` |
| 329 | + - Resamples voxel sizes to ``voxel_size`` |
| 330 | + - Reorients to RAS (``mri_convert --conform`` reorients to LIA) |
| 331 | +
|
| 332 | + Unlike ``mri_convert --conform``, this command does not: |
| 333 | + - Transform data to range [0, 255] |
| 334 | + - Cast to unsigned eight-bit integer |
| 335 | +
|
| 336 | + Parameters |
| 337 | + ---------- |
| 338 | + from_img : object |
| 339 | + Object having attributes ``dataobj``, ``affine``, ``header`` and |
| 340 | + ``shape``. If `out_class` is not None, ``img.__class__`` should be able |
| 341 | + to construct an image from data, affine and header. |
| 342 | + out_shape : sequence, optional |
| 343 | + The shape of the output volume. Default is (256, 256, 256). |
| 344 | + voxel_size : sequence, optional |
| 345 | + The size in millimeters of the voxels in the resampled output. Default |
| 346 | + is 1mm isotropic. |
| 347 | + order : int, optional |
| 348 | + The order of the spline interpolation, default is 3. The order has to |
| 349 | + be in the range 0-5 (see ``scipy.ndimage.affine_transform``) |
| 350 | + cval : scalar, optional |
| 351 | + Value used for points outside the boundaries of the input if |
| 352 | + ``mode='constant'``. Default is 0.0 (see |
| 353 | + ``scipy.ndimage.affine_transform``) |
| 354 | + orientation : str, optional |
| 355 | + Orientation of output image. Default is "RAS". |
| 356 | + out_class : None or SpatialImage class, optional |
| 357 | + Class of output image. If None, use ``from_img.__class__``. |
| 358 | +
|
| 359 | + Returns |
| 360 | + ------- |
| 361 | + out_img : object |
| 362 | + Image of instance specified by `out_class`, containing data output from |
| 363 | + resampling `from_img` into axes aligned to the output space of |
| 364 | + ``from_img.affine`` |
| 365 | + """ |
| 366 | + # Only support 3D images. This can be made more general in the future, once tests |
| 367 | + # are written. |
| 368 | + required_ndim = 3 |
| 369 | + if from_img.ndim != required_ndim: |
| 370 | + raise ValueError("Only 3D images are supported.") |
| 371 | + elif len(out_shape) != required_ndim: |
| 372 | + raise ValueError("`out_shape` must have {} values".format(required_ndim)) |
| 373 | + elif len(voxel_size) != required_ndim: |
| 374 | + raise ValueError("`voxel_size` must have {} values".format(required_ndim)) |
| 375 | + |
| 376 | + start_ornt = io_orientation(from_img.affine) |
| 377 | + end_ornt = axcodes2ornt(orientation) |
| 378 | + transform = ornt_transform(start_ornt, end_ornt) |
| 379 | + |
| 380 | + # Reorient first to ensure shape matches expectations |
| 381 | + reoriented = from_img.as_reoriented(transform) |
| 382 | + |
| 383 | + out_aff = rescale_affine(reoriented.affine, reoriented.shape, voxel_size, out_shape) |
| 384 | + |
| 385 | + # Resample input image. |
| 386 | + out_img = resample_from_to( |
| 387 | + from_img=from_img, to_vox_map=(out_shape, out_aff), order=order, mode="constant", |
| 388 | + cval=cval, out_class=out_class) |
| 389 | + |
| 390 | + return out_img |
0 commit comments