.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "generated\examples\plot_2d_rotations.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code. .. rst-class:: sphx-glr-example-title .. _sphx_glr_generated_examples_plot_2d_rotations.py: ================== In-slice rotations ================== This example illustrates some of the basic ideas underlying affine transformations using in-slice rotations. .. GENERATED FROM PYTHON SOURCE LINES 11-13 Setup ----- .. GENERATED FROM PYTHON SOURCE LINES 13-17 .. code-block:: Python import numpy as np import vreg import vreg.plot as plt .. GENERATED FROM PYTHON SOURCE LINES 18-23 Get data -------- For this illustration we are using coronal images and masks. The mask is static throughout and used as a reference to show the effect of the rotations: .. GENERATED FROM PYTHON SOURCE LINES 23-33 .. code-block:: Python # Coronal images img = vreg.fetch('Dixon_out_phase') # Take out one slice (z=100) for clarity img = img.extract_slice(100) # Left kidney mask mask = vreg.fetch('left_kidney') .. GENERATED FROM PYTHON SOURCE LINES 34-37 Display data ------------ Without rotations, the mask aligns with the image: .. GENERATED FROM PYTHON SOURCE LINES 37-41 .. code-block:: Python plt.overlay_2d(img, mask) .. image-sg:: /generated/examples/images/sphx_glr_plot_2d_rotations_001.png :alt: plot 2d rotations :srcset: /generated/examples/images/sphx_glr_plot_2d_rotations_001.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 42-47 A rotation ---------- Let's rotate the image over an angle of 30 degrees, clockwise, around an axis perpendicular to the slice. This idea is easiest to express when we use a coordinate system defined by the image's axes. .. GENERATED FROM PYTHON SOURCE LINES 47-60 .. code-block:: Python # Define the coordinate system coords = img.affine # Define the rotation vector in image coordinates vec = [0, 0, np.radians(30)] # Perform the rotation rot = img.rotate(vec, coords=coords) # Check the result plt.overlay_2d(rot, mask) .. image-sg:: /generated/examples/images/sphx_glr_plot_2d_rotations_002.png :alt: plot 2d rotations :srcset: /generated/examples/images/sphx_glr_plot_2d_rotations_002.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 61-75 Direction of rotation --------------------- Note that while it appears we have rotated the mask counter clockwise, we have in fact rotated the image clockwise. However, since we use the image as visual reference here, it appears static. A positive angle has created a clockwise rotation here because the volume's reference frame has an x-axis pointing along the rows from left to right, and the y-axis is pointing along the columns from top to bottom. Using the right-hand rule the z-axis therefore points into the screen. Placing the thumb of the right hand along the z-axis, the fingers curl in the clockwise direction, which is the direction corresponding to positive angles. .. GENERATED FROM PYTHON SOURCE LINES 77-87 Center of rotation ------------------ Since we have not specified a rotation center, the rotation was performed around the origin of the volume's reference frame, which is the top left-hand corner in this image. If we want a different rotation center, we can specify that in the call to the rotation function. Let's perform this rotation again, but now rotating around the center of mass of the left kidney. Since the rotation vector is expressed in the coordinate system of the image, we must do the same for the rotation center. .. GENERATED FROM PYTHON SOURCE LINES 87-97 .. code-block:: Python # Find the center of mass center = mask.center_of_mass(coords) # Perform the rotation rot = img.rotate(vec, center, coords=coords) # Check the result plt.overlay_2d(rot, mask) .. image-sg:: /generated/examples/images/sphx_glr_plot_2d_rotations_003.png :alt: plot 2d rotations :srcset: /generated/examples/images/sphx_glr_plot_2d_rotations_003.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 98-106 Rotating values --------------- The rotated image looks exactly the same as the original image because by default ``vreg`` does not modify the values. Instead it rotates the affine matrix which specifies where the values exist in space. However, it is possible to rotate the values instead by setting the *values* flag to True. .. GENERATED FROM PYTHON SOURCE LINES 106-113 .. code-block:: Python # Rotate the values instead of the affine rot = img.rotate(vec, center, coords=coords, values=True) # Check the result plt.overlay_2d(rot, mask) .. image-sg:: /generated/examples/images/sphx_glr_plot_2d_rotations_004.png :alt: plot 2d rotations :srcset: /generated/examples/images/sphx_glr_plot_2d_rotations_004.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 114-123 Reshaping --------- Since the values have been rotated and the affine has stayed the same, the image now appears rotated with a static mask, but some of the values have have been lost because the shape of the value array stays the same by default. We can fix this by setting the *reshape* flag to True, which will increase the field of view to preserve all image values. .. GENERATED FROM PYTHON SOURCE LINES 123-130 .. code-block:: Python # Rotate values and reshape rot = img.rotate(vec, center, coords=coords, values=True, reshape=True) # Check the result plt.overlay_2d(rot, mask) .. image-sg:: /generated/examples/images/sphx_glr_plot_2d_rotations_005.png :alt: plot 2d rotations :srcset: /generated/examples/images/sphx_glr_plot_2d_rotations_005.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 131-144 Affine versus values -------------------- As the image shows, the reshaping option has now preserved all values by enlarging the value array, but the problem remains that many pixels have had to be zero-filled in order to create a rectangular value array. This example illustrates why rotating the affine instead of the values is generally preferred. It does not come with a need to interpolate or modify the values, or fill parts of the image with values that do not properly describe the object. Rotating the affine retains the values exactly as they are, and just assigns them a different location in space. .. GENERATED FROM PYTHON SOURCE LINES 146-161 Active versus passive rotations ------------------------------- The examples above all performed **active** rotations: they physically rotated the image away from it's original position, creating a misalignment with the original kidney mask. An alternative way of looking at a rotation is to reslice the image at a rotated angle, without actually changing it's position in space. This is a **passive** rotation. The effect on the values is the same as an active rotation in the opposite sense, but since it does not change where the values are, it merely provides and alternative picture of the same volume. Let's perform the above rotation again, but now passively using it only to reslice the values. We use the oppositive sign of the rotation vector to get a comparable result as before: .. GENERATED FROM PYTHON SOURCE LINES 161-168 .. code-block:: Python # Perform a passive rotation (aka reslice the volume) rot = img.reslice(rotation=-np.array(vec), center=center, coords=coords) # Check the result plt.overlay_2d(rot, mask) .. image-sg:: /generated/examples/images/sphx_glr_plot_2d_rotations_006.png :alt: plot 2d rotations :srcset: /generated/examples/images/sphx_glr_plot_2d_rotations_006.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 169-173 The rotated image looks exactly the same as in the previous example, but in this case the kidney mask is still in the same place. This is because the volume has not actually been rotated in space - it has merely been resliced at an angle so we see it in a different plane. .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 3.891 seconds) .. _sphx_glr_download_generated_examples_plot_2d_rotations.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_2d_rotations.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_2d_rotations.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: plot_2d_rotations.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_