Controlling Volume Reslice Driver to follow 5DOF inplane view of tool

I’d like show a 5DOF inplane view of needle using the Volume Reslice Driver extension, with the 6th DOF rotation locked in alignment with respect to a canonical axis in the global RAS reference frame, providing a more grounded view of tool paths that remain orientated with respect to the volume.

While the VolumeResliceDriver easily allows for controlling slice views relative to 6DOF pose transforms, as well as with respect to 3 additional orthogonal axis - either fixed to the global RAS reference frame or the relative to tracked transform itself, the fixed RAS modes are useful in only tracking the 3DOF point of a tool tip, while the relative inplane modes are a little too disorientating for real time use. Thus, I’d like to replicate a hybrid of the two modes, that may be common among many IGT visualizations, by locking one rotation axis of an inline slice view to a chosen RAS axis.

Via scripting, I could publish the aligned transforms for each RAS axis variant for a given tool:

"""
============================
Position sending server
============================

Simple application that starts a server that provides a stream of tool trajectories.

from slicer.util import pip_install
pip_install("pyigtl")

Adapted from:
https://github.com/lassoan/pyigtl/blob/d28132d8e9e1cef4ac531d795f5284c8aa739408/examples/example_position_server.py
https://github.com/lassoan/pyigtl/blob/d28132d8e9e1cef4ac531d795f5284c8aa739408/pyigtl/tests/test_basic_comm.py#L87-L93
"""

import pyigtl 

from time import sleep
import numpy as np
from scipy.spatial.transform import Rotation as R

server = pyigtl.OpenIGTLinkServer(port=18944)

timestep = 0
while True:
    if not server.is_connected():
        # Wait for client to connect
        sleep(0.1)
        continue

    # Generate periodic trajectory: Lissajous curve on sphere
    timestep += 1
    radius = 50.0
    center = np.array([0.0, 0.0, -100.0])
    # Use two periodic angles for smooth looping
    phi = (timestep * 0.001) % (2 * np.pi)  # azimuthal
    theta = (timestep * 0.002) % (2 * np.pi) # polar
    x = center[0] + radius * np.sin(theta) * np.cos(phi)
    y = center[1] + radius * np.sin(theta) * np.sin(phi)
    z = center[2] + radius * np.cos(theta)
    position = np.array([x, y, z])

    # Orientation: always point toward center
    forward = center - position
    forward = forward / np.linalg.norm(forward)
    # Create a rotation that aligns Z axis with 'forward'
    align_rot, _ = R.align_vectors([forward], [[0, 0, 1]])
    # Add a twist around the forward axis (drill bit effect)
    twist_rot = R.from_rotvec(theta * 10 * forward)
    # Compose the two rotations: first align, then twist
    rot_obj = twist_rot * align_rot
    rot_matrix = rot_obj.as_matrix()
    # Build 4x4 transform
    tf = np.eye(4)
    tf[:3, :3] = rot_matrix
    tf[:3, 3] = position

    tf_axial = tf.copy()
    # Project 'forward' onto RS plane (zero A component)
    f_proj = forward.copy()
    f_proj[1] = 0
    # Directly align projected vector to Z axis (no need to normalize)
    axial_rot, _ = R.align_vectors([f_proj], [[0, 0, 1]])
    tf_axial[:3, :3] = axial_rot.as_matrix()

    tf_sagittal = tf.copy()
    # Project 'forward' onto SA plane (zero R component)
    f_proj = forward.copy()
    f_proj[2] = 0
    # Directly align projected vector to X axis (no need to normalize)
    sagittal_rot, _ = R.align_vectors([f_proj], [[1, 0, 0]])
    tf_sagittal[:3, :3] = sagittal_rot.as_matrix()

    tf_coronal = tf.copy()
    # Project 'forward' onto AR plane (zero S component)
    f_proj = forward.copy()
    f_proj[0] = 0
    # Directly align projected vector to Y axis (no need to normalize)
    coronal_rot, _ = R.align_vectors([f_proj], [[0, 1, 0]])
    tf_coronal[:3, :3] = coronal_rot.as_matrix()

    tf_msg = pyigtl.TransformMessage(tf, device_name='ToolToRAS')
    server.send_message(tf_msg, wait=True)
    tf_msg = pyigtl.TransformMessage(tf_axial, device_name='ToolOnAxial')
    server.send_message(tf_msg, wait=True)
    tf_msg = pyigtl.TransformMessage(tf_sagittal, device_name='ToolOnSagittal')
    server.send_message(tf_msg, wait=True)
    tf_msg = pyigtl.TransformMessage(tf_coronal, device_name='ToolOnCoronal')
    server.send_message(tf_msg, wait=True)
    # Since we wait until the message is actually sent, the message queue will not be flooded

However, that seems a little excessive in practice, as I’d also like to re-use the Stabilize processing mode via TransformProcessor for low pass filtering of noise from navigation tracking. I tried playing around with the various other processing modes provided by TransformProcessor to collocate all aligned transform computation within Slicer 3D fronted itself, simplifying the use Stabilized transform trees, but couldn’t figure out how to replicate the same alignment as above in python.

Any suggestions using TransformProcessor, or adding such a mode to VolumeResliceDriver?