-
Notifications
You must be signed in to change notification settings - Fork 31
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
How to boost to the center of mass? #134
Comments
It seems to be a bug with 4vecs defined with energy, as defining a 4vec with mass works perfectly fine, as does calculating beta:
Output:
|
Btw: In either way, this behavior should be properly documented. Edit:
|
* Add boostCM_of to clarify #134, supported by scale*D and neg*D. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Refactor to satisfy MyPy. Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
There are some convention-setting choices to make here, such as whether So, on the point of negating a Lorentz vector, ROOT negates all components, regardless of whether the temporal component is energy-like ( >>> import ROOT
>>>
>>> timelike_t = ROOT.Math.PxPyPzEVector(1, 2, 3, 4)
>>> print(timelike_t)
(1,2,3,4)
>>> print(-timelike_t)
(-1,-2,-3,-4)
>>>
>>> timelike_m = ROOT.Math.PxPyPzMVector(1, 2, 3, 4)
>>> print(timelike_m)
(1,2,3,4)
>>> print(-timelike_m)
(-1,-2,-3,-4)
>>>
>>> spacelike_t = ROOT.Math.PxPyPzEVector(1, 2, 3, 0.5)
>>> print(spacelike_t)
(1,2,3,0.5)
>>> print(-spacelike_t)
(-1,-2,-3,-0.5)
>>>
>>> spacelike_m = ROOT.Math.PxPyPzMVector(1, 2, 3, -0.5)
>>> print(spacelike_m)
(1,2,3,-0.5)
>>> print(-spacelike_m)
(-1,-2,-3,0.5) Now, for boosting, It also adds a convenience function for boosting to the center-of-mass (CM), >>> import vector
>>> v = vector.obj(px=1, py=2, pz=3, E=4)
>>>
>>> v.boostCM_of(v)
vector.obj(px=4.440892098500626e-16, py=8.881784197001252e-16, pz=1.7763568394002505e-15, E=1.414213562373094)
>>>
>>> v.boostCM_of(v.to_beta3())
vector.obj(px=0.0, py=0.0, pz=0.0, E=1.414213562373094) To do this same thing, ROOT only has the velocity-based approach (the one with >>> timelike_t.BoostToCM()
<cppyy.gbl.ROOT.Math.DisplacementVector3D<ROOT::Math::Cartesian3D<double>,ROOT::Math::DefaultCoordinateSystemTag> object at 0x56403a345640>
>>> timelike_t.BoostToCM().X()
-0.25
>>> timelike_t.BoostToCM().Y()
-0.5
>>> timelike_t.BoostToCM().Z()
-0.75
>>> print(ROOT.Math.VectorUtil.boost(timelike_t, timelike_t.BoostToCM()))
(0,0,0,1.41421)
>>> timelike_t.M()
1.4142135623730951 The direct equivalent of this in Vector is However, boosting to the center-of-mass of something is the most important use-case for boosting. Sure, there's As for the distinction between the four-momentum ( >>> v.boostCM_of(v)
vector.obj(px=4.440892098500626e-16, py=8.881784197001252e-16, pz=1.7763568394002505e-15, E=1.414213562373094)
>>> v.boostCM_of(v.to_beta3())
vector.obj(px=0.0, py=0.0, pz=0.0, E=1.414213562373094) Notwithstanding this example, boosting with a four-momentum should usually have better numerical precision than the velocity method. Converting a four-momentum into a velocity squashes the infinite range of high momenta/energies onto numbers between |
You also figured out (and edited away) the fact that TLorentzVector worked this way: you had to say TLorentzVector's >>> tlv = ROOT.TLorentzVector(1, 2, 3, 4)
>>> tlv.X(), tlv.Y(), tlv.Z(), tlv.T()
(1.0, 2.0, 3.0, 4.0)
>>> beta3 = tlv.BoostVector()
>>> beta3.X(), beta3.Y(), beta3.Z()
(0.25, 0.5, 0.75)
>>> tlv.Boost(tlv.BoostVector())
>>> tlv.X(), tlv.Y(), tlv.Z(), tlv.T()
(5.65685424949238, 11.31370849898476, 16.97056274847714, 21.213203435596423)
>>>
>>> tlv = ROOT.TLorentzVector(1, 2, 3, 4) # have to reset the TLorentzVector
>>> tlv.X(), tlv.Y(), tlv.Z(), tlv.T()
(1.0, 2.0, 3.0, 4.0)
>>> tlv.Boost(-beta3)
>>> tlv.X(), tlv.Y(), tlv.Z(), tlv.T()
(0.0, 0.0, 0.0, 1.414213562373095)
>>>
>>> v = vector.obj(px=1, py=2, pz=3, E=4)
>>> v
vector.obj(px=1, py=2, pz=3, E=4)
>>> beta3 = v.to_beta3()
>>> beta3
vector.obj(px=0.25, py=0.5, pz=0.75)
>>> v.boost(beta3)
vector.obj(px=5.65685424949238, py=11.31370849898476, pz=16.97056274847714, E=21.213203435596427)
>>>
>>> v.boost(-beta3)
vector.obj(px=0.0, py=0.0, pz=0.0, E=1.414213562373094) |
Thank you very much for the new features and in depth explanation. I learned something new about ROOT here. The new methods are very useful and I think it's now clear what I'm currently part of a group which moves study exercises in particle physics partially using One last question: why does |
That sounds like a good project. I'm looking forward to it! As for why it works when defining the vector with mass, these vectors have weird rules about interpreting negative masses as spacelike vectors. Is it only effectively negating the spatial components, within approximation? It might be getting that effect by accident, since the temporal part might be getting clipped when it's mass instead of energy, and that would make the negation a larger effect in the spatial components. Oh, and I didn't mean to imply that you shouldn't have asked without having the full picture. That's why you ask, after all. I was piecing together what had happened, coming from another project without having thought about this recently. |
I would expect the following code to return a 4Vec with values close to 0 for px, py and pz and the rest mass as energy, but it does not:
Output:
vector.obj(px=-0.026700724532754565, py=1.5960592536320295, pz=-3.207801869150135, E=-6.231808367987319)
Am I missing something obvious here?
This exact same code produces a vector of the particle in the rest frame with root.
Edit:
particle.boost(particle)
andparticle.boost_p4(particle)
with either sign don't work either.The text was updated successfully, but these errors were encountered: