# ACPC transform question

**URL:** <https://discourse.slicer.org/t/acpc-transform-question/3525>\
**Category:** Support\
**Tags:** transforms\
**Created:** [July 19, 2018, 2:50pm UTC](https://discourse.slicer.org/t/acpc-transform-question/3525 "2018-07-19T14:50:10Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![shebaelena](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/shebaelena/32/9708_2.png) [@shebaelena](https://discourse.slicer.org/u/shebaelena)\
**Post date:** [July 19, 2018, 2:50pm UTC](https://discourse.slicer.org/t/acpc-transform-question/3525/1 "2018-07-19T14:50:10Z")

</div>

Hello,

I have been trying to figure out how to transform a scan so that it aligns to the ACPC plane. I’ve tried using this module ([https://www.slicer.org/wiki/Documentation/4.8/Modules/ACPCTransform](https://www.slicer.org/wiki/Documentation/4.8/Modules/ACPCTransform)) and placing fiducial points on different slices to transform the scan, but have been unsuccessful. Can anyone explain how I can do this? Also, is there a way to overlay a grid on the scan or in some way calculate just horizontal distance with the ruler?

Thank you!

---

<div class="post-metadata">

**Author:** ![Fernando](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/fernando/32/5640_2.png) [@Fernando](https://discourse.slicer.org/u/Fernando)\
**Post date:** [July 19, 2018, 8:59pm UTC](https://discourse.slicer.org/t/acpc-transform-question/3525/2 "2018-07-19T20:59:00Z")

</div>

Hi Alexis,

You can try this code on the Python console:

```python
import numpy as np
import SampleData

def getSampleVolume():
    # Download MRHead
    sampleDataLogic = SampleData.SampleDataLogic()
    volumeNode = sampleDataLogic.downloadMRHead()
    return volumeNode

def getMatrixToACPC(ac, pc, ih):
    # Anteroposterior axis
    pcAc = ac - pc
    yAxis = pcAc / np.linalg.norm(pcAc)
    # Lateral axis
    acIhDir = ih - ac
    xAxis = np.cross(yAxis, acIhDir)
    xAxis /= np.linalg.norm(xAxis)
    # Rostrocaudal axis
    zAxis = np.cross(xAxis, yAxis)
    # Rotation matrix
    rotation = np.vstack([xAxis, yAxis, zAxis])
    # AC in rotated space
    translation = -np.dot(rotation, ac)
    # Build homogeneous matrix
    matrix = np.eye(4)
    matrix[:3, :3] = rotation
    matrix[:3, 3] = translation
    return matrix

def getTransformNodeFromNumpyMatrix(matrix, name=None):
    # Create VTK matrix object
    vtkMatrix = vtk.vtkMatrix4x4()
    for row in range(4):
        for col in range(4):
            vtkMatrix.SetElement(row, col, matrix[row, col])
    # Create MRML transform node
    transformNode = slicer.mrmlScene.AddNewNodeByClass(
        'vtkMRMLLinearTransformNode')
    if name is not None:
        transformNode.SetName(name)
    transformNode.SetAndObserveMatrixTransformToParent(vtkMatrix)
    return transformNode

# I defined these on MRHead
ac = np.array([-0.0641399910762672, 17.61291529545006, 5.009494772024041])
pc = np.array([-0.5843405105866637, -10.4779127581112, 3.044020167647495])
ih = np.array([-1.1045410300970602, 1.746799450383008, 45.04402016764749])

volumeNode = getSampleVolume()
matrix = getMatrixToACPC(ac, pc, ih)
transformNode = getTransformNodeFromNumpyMatrix(matrix, name='World to ACPC')

# Create markups node with AC, PC and an interhemispheric point
markupsNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLMarkupsFiducialNode')
markupsNode.SetName('AC-PC-IH')
markupsNode.AddFiducialFromArray(ac, 'AC')
markupsNode.AddFiducialFromArray(pc, 'PC')
markupsNode.AddFiducialFromArray(ih, 'IH')

# Apply transform to volume node and markups node
volumeNode.SetAndObserveTransformNodeID(transformNode.GetID())
markupsNode.SetAndObserveTransformNodeID(transformNode.GetID())

# Fit image to slices
applicationLogic = slicer.app.applicationLogic()
applicationLogic.FitSliceToAll()

# Center views on AC
markupsLogic = slicer.modules.markups.logic()
acIndex = 0
markupsLogic.JumpSlicesToNthPointInMarkup(markupsNode.GetID(), acIndex)

```

By the way, looking forward to showing examples like these in a Jupyter Notebook 🙂

> [@Jupyter notebooks are now usable in 3D Slicer](https://discourse.slicer.org/t/jupyter-notebooks-are-now-usable-in-3d-slicer/3438):
>
> We worked hard with @jcfr during the during [Slicer project week in Gran Canaria](https://na-mic.github.io/ProjectWeek/PW28_2018_GranCanaria/) and we are excited to share one of the newest developments: [Jupyter notebook](https://jupyter.org/) support. You can create interactive Python notebooks to run Slicer code and show resulting text data or slicer/3D view content in the notebook. Great for experimenting and sharing code and results with others. [image] See an example notebook [here](https://github.com/lassoan/SlicerNotebooks/blob/master/My%20second%20notebook.ipynb), which shows loading of a sample data set, display of a slice view, creation and display of a…

---

<div class="post-metadata">

**Author:** ![lassoan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lassoan/32/13_2.png) [@lassoan](https://discourse.slicer.org/u/lassoan)\
**Post date:** [July 20, 2018, 4:53am UTC](https://discourse.slicer.org/t/acpc-transform-question/3525/3 "2018-07-20T04:53:02Z")

</div>

> [@shebaelena](#):
>
> have been unsuccessful

These may help (they are accurate for Slicer 3.6, but the behavior is not that much different on Slicer 4.9):

- [Documentation:Nightly:Registration:RegistrationLibrary:RegLib C15 - Slicer Wiki](https://www.slicer.org/wiki/Documentation:Nightly:Registration:RegistrationLibrary:RegLib_C15)
- [PPT - Slicer3 Tutorial: Registration Library Case 15 AC-PC Alignment PowerPoint Presentation - ID:5393167](https://www.slideserve.com/jacoba/slicer3-tutorial-registration-library-case-15-ac-pc-alignment)
- [https://www.slicer.org/wiki/Documentation/Nightly/Modules/ACPCTransform](https://www.slicer.org/wiki/Documentation/Nightly/Modules/ACPCTransform)

If you still have problems, then please describe what you did exactly, what you expected to happen, and what happened instead.
