@pimms.value<EOL><INDENT>def alignment_matrix(pre_affine, center, center_right):<DEDENT>
mtx = np.eye(<NUM_LIT:4>) if pre_affine is None else pre_affine<EOL>cmtx = np.eye(<NUM_LIT:4>)<EOL>if center is not None:<EOL><INDENT>tmp = alignment_matrix_3D(center, [<NUM_LIT:0>,<NUM_LIT:0>,<NUM_LIT:1>])<EOL>cmtx[<NUM_LIT:0>:<NUM_LIT:3>,<NUM_LIT:0>:<NUM_LIT:3>] = tmp<EOL>mtx = cmtx.dot(mtx)<EOL><DEDENT>crmtx = np.eye(<NUM_LIT:4>)<EOL>if center_right is not None:<EOL><INDENT>cr = cmtx.dot(np.concatenate([center_right, [<NUM_LIT:1>]]))[:<NUM_LIT:3>]<EOL>ang = np.arctan2(cr[<NUM_LIT:1>], cr[<NUM_LIT:0>])<EOL>crmtx[<NUM_LIT:0>:<NUM_LIT:3>,<NUM_LIT:0>:<NUM_LIT:3>] = rotation_matrix_3D([<NUM_LIT:0>,<NUM_LIT:0>,<NUM_LIT:1>], -ang)<EOL>mtx = crmtx.dot(mtx)<EOL><DEDENT>return pimms.imm_array(mtx)<EOL>
proj.alignment_matrix is a 4x4 matrix that aligns the 3D spherical mesh such that the center
of the projection lies on the positive z-axis and the center_right of the projection lies in
the x-z plane with a positive x value.

Note that the alignment_matrix applies the pre_affine prior to determining the rotation of
the center and center_right; accordingly, the center should be specified in post-pre_affine
transfomration coordinates.