def fibonacci_sphere_projecton_matrix(number_of_projections, source_detector_distance,
detector_spacing, source_isocenter_distance, detector_origin,
swap_axis=False, *args, **kwargs):
# init empty
# assert len(pts) == number_of_projections
# TODO: Document this function on your own. Could not be documented by the model.
# TODO: Document this function on your own. Could not be documented by the model.
pts = fibonacci_sphere(number_of_projections)
projection_matrices = np.zeros((len(pts), 3, 4))
x_axis = np.array([1., 0., 0.])
y_axis = np.array([0., 1., 0.])
z_axis = np.array([0., 0., 1.])
u_dir = y_axis
if swap_axis:
v_dir = x_axis
else:
v_dir = -x_axis
intrinsic_params_mat = np.eye(3, 3)
for i in range(2):
intrinsic_params_mat[i, i] = source_detector_distance / detector_spacing[1 - i]
# calc and set detector origin
# we need t_x and t_y, and follow the [z,y,x] convention
intrinsic_params_mat[0, 2] = detector_origin[-1] / detector_spacing[-1] * -1
intrinsic_params_mat[1, 2] = detector_origin[-2] / detector_spacing[-2] * -1
for p in range(len(pts)):
extrinsic_params_mat = np.eye(4, 4)
R_to_plane = np.eye(4, 4)
R_to_plane[0:3, 0:3] = np.array([z_axis, np.cross(z_axis, x_axis), -x_axis])
axis_align_R = np.eye(4, 4)
axis_align_R[0:3, 0] = u_dir
axis_align_R[0:3, 1] = v_dir
axis_align_R[0:3, 2] = np.cross(u_dir, v_dir)
axis_align_R = axis_align_R.T
translation = np.eye(4, 4)
translation[0:4, 3] = np.array([0, 0, source_isocenter_distance, 1])
R_to_pts = np.eye(4, 4)
R_to_pts[0:3, 0:3] = rotation_matrix_from_points(pts[p],
np.array([0, 0, source_isocenter_distance])
)
extrinsic_params_mat = np.dot(np.dot(np.dot(translation, axis_align_R), R_to_pts), R_to_plane)
extrinsic_params_mat = extrinsic_params_mat / extrinsic_params_mat[3, 3]
projection_matrices[p][0:3, 0:3] = np.dot(intrinsic_params_mat, extrinsic_params_mat[0:3, 0:3])
projection_matrices[p][0:3, 3] = np.dot(intrinsic_params_mat, extrinsic_params_mat[0:3, 3])
return projection_matrices