# Get C-arm angles from 3D view orientation

**URL:** <https://discourse.slicer.org/t/get-c-arm-angles-from-3d-view-orientation/24435>\
**Category:** Support\
**Tags:** fluoroscopy\
**Created:** [July 21, 2022, 5:24pm UTC](https://discourse.slicer.org/t/get-c-arm-angles-from-3d-view-orientation/24435 "2022-07-21T17:24:45Z")\
**Posts on this page:** 1\
**Showing post:** 3

<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 21, 2022, 7:03pm UTC](https://discourse.slicer.org/t/get-c-arm-angles-from-3d-view-orientation/24435/3 "2022-07-21T19:03:02Z")

</div>

You can copy-paste this code snippet to the Python console to show the anatomical angles (LAO/RAO, CRA/CAU) of the C-arm in the corner of a 3D view:

```python
threeDViewIndex = 0 # change this to show angles in a different 3D view

def positionerAngleFromViewNormal(viewNormal):
    # According to https://www5.informatik.uni-erlangen.de/Forschung/Publikationen/2014/Koch14-OVA.pdf
    nx = -viewNormal[0] # L
    ny = -viewNormal[1] # P
    nz = viewNormal[2] # S
    import math
    if abs(ny) > 1e-6:
        primaryAngleDeg = math.atan(-nx/ny) * 180.0 / math.pi
    elif nx >= 0:
        primaryAngleDeg = 90.0
    else:
        primaryAngleDeg = -90.0
    secondaryAngleDeg = math.asin(nz) * 180.0 / math.pi
    return [primaryAngleDeg, secondaryAngleDeg]

def formatPositionerAngle(positionerAngles):
    primaryAngleDeg, secondaryAngleDeg = positionerAngles
    text = f'{"RAO" if primaryAngleDeg < 0 else "LAO"} {abs(primaryAngleDeg):.1f}\n'
    text += f'{"CRA" if secondaryAngleDeg < 0 else "CAU"} {abs(secondaryAngleDeg):.1f}'
    return text

def cameraUpdated(cameraNode, view):
    viewNormal = cameraNode.GetCamera().GetDirectionOfProjection()
    positionerAngleText = formatPositionerAngle(positionerAngleFromViewNormal(viewNormal))
    view.cornerAnnotation().SetText(vtk.vtkCornerAnnotation.UpperRight, positionerAngleText)
    view.cornerAnnotation().GetTextProperty().SetColor(1,1,0) # yellow
    view.scheduleRender()

layoutManager = slicer.app.layoutManager()
view = layoutManager.threeDWidget(threeDViewIndex).threeDView()
threeDViewNode = view.mrmlViewNode()
cameraNode = slicer.modules.cameras.logic().GetViewActiveCameraNode(threeDViewNode)
cameraObservation = cameraNode.AddObserver(vtk.vtkCommand.ModifiedEvent, lambda caller, event, view=view: cameraUpdated(caller, view))

cameraUpdated(cameraNode, view)

# Execute the next line to stop updating the positioner angles in the view corner
# cameraNode.RemoveObserver(cameraObservation)

```

[https://us1.discourse-cdn.com/flex002/uploads/slicer/original/3X/f/e/fe59764902aeb19599d558cd3b73a7ac4fbecf1a.mp4](https://us1.discourse-cdn.com/flex002/uploads/slicer/original/3X/f/e/fe59764902aeb19599d558cd3b73a7ac4fbecf1a.mp4)

We are developing a fluoro simulator module for interventional cardiology as part of the SlicerHeart project. The module will be able to display not just the angles but simulated fluoro images and compute optimal viewing angles, etc. We’ll release it when the results are first published - probably within a year.

---

_[View the full topic](https://discourse.slicer.org/t/get-c-arm-angles-from-3d-view-orientation/24435)._
