MCPcopy Create free account
hub / github.com/Project-MONAI/MONAI / zoom_affine

Function zoom_affine

monai/data/utils.py:798–847  ·  view source on GitHub ↗

To make column norm of `affine` the same as `scale`. If diagonal is False, returns an affine that combines orthogonal rotation and the new scale. This is done by first decomposing `affine`, then setting the zoom factors to `scale`, and composing a new affine; the shearing factors a

(affine: np.ndarray, scale: np.ndarray | Sequence[float], diagonal: bool = True)

Source from the content-addressed store, hash-verified

796
797
798def zoom_affine(affine: np.ndarray, scale: np.ndarray | Sequence[float], diagonal: bool = True):
799 """
800 To make column norm of `affine` the same as `scale`. If diagonal is False,
801 returns an affine that combines orthogonal rotation and the new scale.
802 This is done by first decomposing `affine`, then setting the zoom factors to
803 `scale`, and composing a new affine; the shearing factors are removed. If
804 diagonal is True, returns a diagonal matrix, the scaling factors are set
805 to the diagonal elements. This function always return an affine with zero
806 translations.
807
808 Args:
809 affine (nxn matrix): a square matrix.
810 scale: new scaling factor along each dimension. if the components of the `scale` are non-positive values,
811 will use the corresponding components of the original pixdim, which is computed from the `affine`.
812 diagonal: whether to return a diagonal scaling matrix.
813 Defaults to True.
814
815 Raises:
816 ValueError: When ``affine`` is not a square matrix.
817 ValueError: When ``scale`` contains a nonpositive scalar.
818
819 Returns:
820 the updated `n x n` affine.
821
822 """
823
824 affine = np.array(affine, dtype=float, copy=True)
825 if len(affine) != len(affine[0]):
826 raise ValueError(f"affine must be n x n, got {len(affine)} x {len(affine[0])}.")
827 scale_np = np.array(scale, dtype=float, copy=True)
828
829 d = len(affine) - 1
830 # compute original pixdim
831 norm = affine_to_spacing(affine, r=d)
832 if len(scale_np) < d: # defaults based on affine
833 scale_np = np.append(scale_np, norm[len(scale_np) :])
834 scale_np = scale_np[:d]
835 scale_np = np.asarray(fall_back_tuple(scale_np, norm))
836
837 scale_np[scale_np == 0] = 1.0
838 if diagonal:
839 return np.diag(np.append(scale_np, [1.0]))
840 rzs = affine[:-1, :-1] # rotation zoom scale
841 zs = np.linalg.cholesky(rzs.T @ rzs).T
842 rotation = rzs @ np.linalg.inv(zs)
843 s = np.sign(np.diag(zs)) * np.abs(scale_np)
844 # construct new affine with rotation and zoom
845 new_affine = np.eye(len(affine))
846 new_affine[:-1, :-1] = rotation @ np.diag(s)
847 return new_affine
848
849
850def compute_shape_offset(

Callers 3

__call__Method · 0.90
test_correctMethod · 0.90
test_diagonalMethod · 0.90

Calls 4

fall_back_tupleFunction · 0.90
affine_to_spacingFunction · 0.85
arrayMethod · 0.80
appendMethod · 0.45

Tested by 2

test_correctMethod · 0.72
test_diagonalMethod · 0.72

Used in the wild real call sites across dependent graphs

searching dependent graphs…