I recently stumbled over the method TVector3::RotateUz(), which did not work as expected for us. I understand that the class TVector3 is legacy, but it is still in the ROOT distribution, and we are making use of it.
The documentation says:
v1.RotateUz(direction) transforms from the rotated frame (z’ parallel to direction…) to the (x,y,z,) frame.
Implementation in TVector3.cxx:
void TVector3::RotateUz(const TVector3& NewUzVector) {
Double_t u1 = NewUzVector.fX;
Double_t u2 = NewUzVector.fY;
Double_t u3 = NewUzVector.fZ;
Double_t up = u1*u1 + u2*u2;
if (up) {
up = TMath::Sqrt(up);
Double_t px = fX, py = fY, pz = fZ;
fX = (u1*u3*px - u2*py + u1*up*pz)/up;
fY = (u2*u3*px + u1*py + u2*up*pz)/up;
fZ = (u3*u3*px - px + u3*up*pz)/up;
} else if (u3 < 0.) { fX = -fX; fZ = -fZ; } // phi=0 teta=pi
else {};
}
Now consider the special case when NewUzVector = (u1, 0, u3) is in the x-z plane. Then we should have a rotation around the y = y’ axis, which should give
fX = u3 * px + u1 * pz
fY = py
fZ = -u1 * px * u3 * pz
But from the implementation above, we get with up = sqrt(u1*u1) = abs(u1):
fX = u1 / abs(u1) * u3 * px + u1 * pz
fY = u1 / abs(u1) * py
fZ = -abs(u1) * px + u3 * pz (exploiting the normalisation, i.e. u1*u1+u3*u3 = 1)
This corresponds to the expectation only if u1 >= 0, i.e., for rotations between 0 and pi. In other cases, fX and fY are mirrored (rotated by pi) in the xy plane.
Can you confirm my findings, or do I misinterpret the method RotateUz?