Transform an image using an Affine transform with the given
        rotation parameters.  Return the transform if X=None.

        Arguments
        ---------
        X : ANTsImage
            Image to transform

        y : ANTsImage (optional)
            Another image to transform

        Returns
        -------
        ANTsImage if y is None, else a tuple of ANTsImage types

        Examples
        --------
        >>> import ants
        >>> img = ants.image_read(ants.get_data('ch2'))
        >>> tx = ants.contrib.Rotate3D(rotation=(10,-5,12))
        >>> img2 = tx.transform(img)

def transform(self, X=None, y=None):
        """
        Transform an image using an Affine transform with the given
        rotation parameters.  Return the transform if X=None.

        Arguments
        ---------
        X : ANTsImage
            Image to transform

        y : ANTsImage (optional)
            Another image to transform

        Returns
        -------
        ANTsImage if y is None, else a tuple of ANTsImage types

        Examples
        --------
        >>> import ants
        >>> img = ants.image_read(ants.get_data('ch2'))
        >>> tx = ants.contrib.Rotate3D(rotation=(10,-5,12))
        >>> img2 = tx.transform(img)
        """
        # unpack zoom range
        rotation_x, rotation_y, rotation_z = self.rotation

        # Rotation about X axis
        theta_x = math.pi / 180 * rotation_x
        rotate_matrix_x = np.array([[1, 0,                  0,                 0],
                                    [0, math.cos(theta_x), -math.sin(theta_x), 0],
                                    [0, math.sin(theta_x),  math.cos(theta_x), 0],
                                    [0,0,0,1]])

        # Rotation about Y axis
        theta_y = math.pi / 180 * rotation_y
        rotate_matrix_y = np.array([[math.cos(theta_y),  0, math.sin(theta_y), 0],
                                    [0,                  1, 0,                 0],
                                    [-math.sin(theta_y), 0, math.cos(theta_y), 0],
                                    [0,0,0,1]])

        # Rotation about Z axis
        theta_z = math.pi / 180 * rotation_z
        rotate_matrix_z = np.array([[math.cos(theta_z), -math.sin(theta_z), 0, 0],
                                    [math.sin(theta_z),  math.cos(theta_z), 0, 0],
                                    [0,                0,                   1, 0],
                                    [0,0,0,1]])
        rotate_matrix = rotate_matrix_x.dot(rotate_matrix_y).dot(rotate_matrix_z)[:3,:]

        self.tx.set_parameters(rotate_matrix)
        if self.lazy or X is None:
            return self.tx
        else:
            return self.tx.apply_to_image(X, reference=self.reference)